Compare commits

...

16 Commits
v1.0.0 ... main

Author SHA1 Message Date
luiz 767e0cf9ae Merge pull request 'Include identities to user claims' (#9) from feature/Identities into main
Reviewed-on: #9
2025-03-25 12:28:58 +00:00
Luiz Vasconcelos 59ff04dbbc Include identities to user claims 2025-03-25 13:27:03 +01:00
luiz 5a2083aef0 Merge pull request 'Return nil if claims are not present in request' (#8) from bugfix/emptyUser into main
Reviewed-on: #8
2025-02-19 22:50:57 +00:00
Luiz Vasconcelos d272cfd026 Return nil if claims are not present in request 2025-02-19 23:48:53 +01:00
luiz c1b41684c5 Merge pull request 'Removed unnecessary print' (#7) from fix/cleanPrint into main
Reviewed-on: #7
2025-02-15 09:44:04 +00:00
Luiz Vasconcelos 77f4d32386 Removed unnecessary print 2025-02-15 10:37:32 +01:00
luiz 2343eb2000 Merge pull request 'Added missing return statement' (#6) from bugfix/adminRoute into main
Reviewed-on: #6
2024-11-24 16:48:10 +00:00
Luiz Vasconcelos 5cc3dcad9f Added missing return statement 2024-11-24 17:47:22 +01:00
luiz 43c2abf138 Merge pull request 'Add middleware for AdminRouter and added IsAdmin function' (#5) from feature/admin into main
Reviewed-on: #5
2024-11-24 15:52:53 +00:00
Luiz Vasconcelos 9d813bfd43 Add middleware for AdminRouter and added IsAdmin function 2024-11-24 16:50:11 +01:00
luiz 29dd3bb2bb Merge pull request 'Remove unnecessary logging' (#4) from bugfix/removeLog into main
Reviewed-on: #4
2024-10-29 09:45:14 +00:00
Luiz Vasconcelos 918cc5713d Remove unnecessary logging 2024-10-29 10:43:15 +01:00
luiz f0bbfa9bb2 Merge pull request 'Added sub to userClaims' (#3) from feature/sub into main
Reviewed-on: #3
2024-10-27 15:14:34 +00:00
Luiz Vasconcelos 33ebf1dd0a Added sub to userClaims 2024-10-27 16:14:08 +01:00
luiz b47d5b2bbe Merge pull request 'Add option for protected router with statuscode' (#2) from feature/middleware into main
Reviewed-on: #2
2024-10-27 14:28:37 +00:00
Luiz Vasconcelos 65699b2d46 Add option for protected router with statuscode 2024-10-27 15:27:53 +01:00
3 changed files with 75 additions and 17 deletions

View File

@ -4,7 +4,6 @@ import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"log"
"net/http"
"time"
@ -27,12 +26,21 @@ func NewHandler(oauth2Config *oauth2.Config, session SessionStorer, verifier *oi
}, nil
}
type Identity struct {
UserID string `json:"userId"`
ProviderName string `json:"providerName"`
ProviderType string `json:"providerType"`
}
type UserClaims struct {
Email string `json:"email"`
Verified bool `json:"email_verified"`
Name string `json:"given_name"`
Username string `json:"cognito:username"`
Picture string `json:"picture"`
Sub string `json:"sub"`
Groups []string `json:"cognito:groups"`
Identities []*Identity `json:"identities"`
}
func generateState() (string, error) {
@ -47,19 +55,21 @@ func generateState() (string, error) {
func (h *Handlers) SignIn(w http.ResponseWriter, r *http.Request) {
state, err := generateState()
if err != nil {
log.Println("Failed to generate state")
log.Printf("Failed to generate state: %v", err)
http.Error(w, "Something went wrong", http.StatusInternalServerError)
return
}
session, err := h.session.Get(r)
if err != nil {
log.Printf("Failed to get session: %v", err)
http.Error(w, "Failed to get session", http.StatusInternalServerError)
return
}
session.Values["state"] = state
err = session.Save(r, w)
if err != nil {
log.Printf("Failed to save session: %v", err)
http.Error(w, "Failed to save session", http.StatusInternalServerError)
return
}
@ -73,6 +83,7 @@ func (h *Handlers) CallbackHandler(w http.ResponseWriter, r *http.Request) {
session, err := h.session.Get(r)
if err != nil {
log.Printf("Failed to verify ID Token: %v", err)
http.Error(w, "Failed to get session", http.StatusInternalServerError)
return
}
@ -120,7 +131,6 @@ func (h *Handlers) CallbackHandler(w http.ResponseWriter, r *http.Request) {
session.Values["access_token"] = oauth2Token.AccessToken
session.Values["user_info"] = claims
fmt.Println(claims)
session.Options.MaxAge = int(oauth2Token.Expiry.Sub(time.Now()).Seconds())
err = session.Save(r, w)
if err != nil {

View File

@ -2,10 +2,10 @@ package cauth
import (
"context"
"fmt"
"github.com/lestrrat-go/jwx/jwk"
"log"
"net/http"
"github.com/lestrrat-go/jwx/jwk"
)
type contextKey string
@ -40,25 +40,25 @@ func (m *Middleware) AddUserInfo(next http.Handler) http.Handler {
return
}
userInfo := session.Values["user_info"]
fmt.Println(userInfo)
ctx := context.WithValue(r.Context(), userContextKey, userInfo)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
// ProtectedRoute Checks if session and token are present, if not return a 401 response
func (m *Middleware) ProtectedRoute(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session, err := m.s.Get(r)
if err != nil {
http.Redirect(w, r, "/signin", http.StatusSeeOther)
w.WriteHeader(http.StatusUnauthorized)
return
}
token := session.Values["access_token"]
if token == "" || token == nil {
http.Redirect(w, r, "/signin", http.StatusSeeOther)
w.WriteHeader(http.StatusUnauthorized)
return
}
@ -66,6 +66,52 @@ func (m *Middleware) ProtectedRoute(next http.Handler) http.Handler {
})
}
// ProtectedRouteWithRedirect Checks if session and token are present, if not return a redirect to /login
func (m *Middleware) ProtectedRouteWithRedirect(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session, err := m.s.Get(r)
if err != nil {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
token := session.Values["access_token"]
if token == "" || token == nil {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
next.ServeHTTP(w, r)
})
}
// IsAdmin Checks if admin group is present
func IsAdmin(groups []string) bool {
for _, group := range groups {
if group == "admin" {
return true
}
}
return false
}
// AdminProtectedRoute Checks if user is member of admin group, if not return forbidden
func (m *Middleware) AdminProtectedRoute(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
userOptional := r.Context().Value(userContextKey)
if userOptional != nil {
user := userOptional.(UserClaims)
if IsAdmin(user.Groups) {
next.ServeHTTP(w, r)
return
}
}
http.Error(w, "Forbidden", http.StatusForbidden)
})
}
func GetUserFromContext(r *http.Request) *UserClaims {
userOptional := r.Context().Value(userContextKey)
if userOptional != nil {
@ -73,5 +119,5 @@ func GetUserFromContext(r *http.Request) *UserClaims {
return &user
}
return &UserClaims{}
return nil
}

View File

@ -3,13 +3,14 @@ package cauth
import (
"context"
"encoding/gob"
"log"
"net/http"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/gorilla/sessions"
"github.com/rbcervilla/redisstore/v9"
"github.com/redis/go-redis/v9"
"golang.org/x/oauth2"
"log"
"net/http"
)
const SESSION_NAME = "auth-session"
@ -31,6 +32,7 @@ type SessionStorer interface {
func NewRedisSessionStore(params RedisSessionParams) (SessionStorer, error) {
gob.Register(&oauth2.Token{})
gob.Register(oidc.IDToken{})
gob.Register(Identity{})
gob.Register(UserClaims{})
client := redis.NewClient(&redis.Options{
Addr: params.RedisAddress,