79 lines
2.1 KiB
Go
79 lines
2.1 KiB
Go
|
package oidcgin
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net/http"
|
||
|
|
||
|
"git.icod.de/dalu/ginoidc/ginerror"
|
||
|
"git.icod.de/dalu/oidc"
|
||
|
"git.icod.de/dalu/oidc/options"
|
||
|
"github.com/gin-gonic/gin"
|
||
|
)
|
||
|
|
||
|
// New returns an OpenID Connect (OIDC) discovery handler (middleware)
|
||
|
// to be used with `gin`.
|
||
|
func New(setters ...options.Option) gin.HandlerFunc {
|
||
|
oidcHandler, err := oidc.NewHandler(setters...)
|
||
|
if err != nil {
|
||
|
panic(fmt.Sprintf("oidc discovery: %v", err))
|
||
|
}
|
||
|
return toGinHandler(oidcHandler.ParseToken, setters...)
|
||
|
}
|
||
|
|
||
|
func onError(c *gin.Context, errorHandler options.ErrorHandler, statusCode int, description options.ErrorDescription, err error) {
|
||
|
c.AbortWithStatusJSON(statusCode, gin.H{"error": err.Error()})
|
||
|
}
|
||
|
|
||
|
func toGinHandler(parseToken oidc.ParseTokenFunc, setters ...options.Option) gin.HandlerFunc {
|
||
|
opts := options.New(setters...)
|
||
|
|
||
|
return func(c *gin.Context) {
|
||
|
var errorTypes []ginerror.Error
|
||
|
|
||
|
ctx := c.Request.Context()
|
||
|
|
||
|
tokenString, err := oidc.GetTokenString(c.Request.Header.Get, opts.TokenString)
|
||
|
if err != nil {
|
||
|
if !opts.Permissive {
|
||
|
onError(c, opts.ErrorHandler, http.StatusBadRequest, options.GetTokenErrorDescription, err)
|
||
|
return
|
||
|
} else {
|
||
|
errorTypes = append(errorTypes, ginerror.Error{
|
||
|
Description: options.GetTokenErrorDescription,
|
||
|
Error: err,
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
token, err := parseToken(ctx, tokenString)
|
||
|
if err != nil {
|
||
|
if !opts.Permissive {
|
||
|
onError(c, opts.ErrorHandler, http.StatusUnauthorized, options.ParseTokenErrorDescription, err)
|
||
|
return
|
||
|
} else {
|
||
|
errorTypes = append(errorTypes, ginerror.Error{
|
||
|
Description: options.GetTokenErrorDescription,
|
||
|
Error: err,
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tokenClaims, err := token.AsMap(ctx)
|
||
|
if err != nil {
|
||
|
if !opts.Permissive {
|
||
|
onError(c, opts.ErrorHandler, http.StatusUnauthorized, options.ConvertTokenErrorDescription, err)
|
||
|
return
|
||
|
} else {
|
||
|
errorTypes = append(errorTypes, ginerror.Error{
|
||
|
Description: options.GetTokenErrorDescription,
|
||
|
Error: err,
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
c.Set(string(opts.ClaimsContextKeyName), tokenClaims)
|
||
|
c.Set(string(opts.ErrorsContextKeyName), errorTypes)
|
||
|
c.Next()
|
||
|
}
|
||
|
}
|