change some interfaces
This commit is contained in:
parent
bfbd4adb1c
commit
eaf47fde8e
10 changed files with 130 additions and 20 deletions
|
@ -36,6 +36,18 @@ type AuthorizeValidator interface {
|
|||
//Deprecated: ValidationAuthorizer exists for historical compatibility. Use ValidationAuthorizer itself
|
||||
type ValidationAuthorizer AuthorizeValidator
|
||||
|
||||
func authorizeHandler(authorizer Authorizer) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
Authorize(w, r, authorizer)
|
||||
}
|
||||
}
|
||||
|
||||
func authorizeCallbackHandler(authorizer Authorizer) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
AuthorizeCallback(w, r, authorizer)
|
||||
}
|
||||
}
|
||||
|
||||
//Authorize handles the authorization request, including
|
||||
//parsing, validating, storing and finally redirecting to the login handler
|
||||
func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) {
|
||||
|
@ -152,7 +164,7 @@ func ValidateAuthReqIDTokenHint(ctx context.Context, idTokenHint string, verifie
|
|||
if idTokenHint == "" {
|
||||
return "", nil
|
||||
}
|
||||
claims, err := verifier.VerifyIDToken(ctx, idTokenHint)
|
||||
claims, err := VerifyIDTokenHint(ctx, idTokenHint, verifier)
|
||||
if err != nil {
|
||||
return "", ErrInvalidRequest("The id_token_hint is invalid. If you have any questions, you may contact the administrator of the application.")
|
||||
}
|
||||
|
|
|
@ -279,12 +279,11 @@ func (p *DefaultOP) ClientJWTVerifier() rp.Verifier {
|
|||
return p.verifier
|
||||
}
|
||||
|
||||
func (p *DefaultOP) HandleReady(w http.ResponseWriter, r *http.Request) {
|
||||
probes := []ProbesFn{
|
||||
func (p *DefaultOP) Probes() []ProbesFn {
|
||||
return []ProbesFn{
|
||||
ReadySigner(p.Signer()),
|
||||
ReadyStorage(p.Storage()),
|
||||
}
|
||||
Readiness(w, r, probes...)
|
||||
}
|
||||
|
||||
func (p *DefaultOP) HandleKeys(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -10,6 +10,12 @@ type KeyProvider interface {
|
|||
Storage() Storage
|
||||
}
|
||||
|
||||
func keysHandler(k KeyProvider) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
Keys(w, r, k)
|
||||
}
|
||||
}
|
||||
|
||||
func Keys(w http.ResponseWriter, r *http.Request, k KeyProvider) {
|
||||
keySet, err := k.Storage().GetKeySet(r.Context())
|
||||
if err != nil {
|
||||
|
|
20
pkg/op/op.go
20
pkg/op/op.go
|
@ -16,15 +16,9 @@ const (
|
|||
|
||||
type OpenIDProvider interface {
|
||||
Configuration
|
||||
HandleReady(w http.ResponseWriter, r *http.Request)
|
||||
HandleDiscovery(w http.ResponseWriter, r *http.Request)
|
||||
HandleAuthorize(w http.ResponseWriter, r *http.Request)
|
||||
HandleAuthorizeCallback(w http.ResponseWriter, r *http.Request)
|
||||
HandleExchange(w http.ResponseWriter, r *http.Request)
|
||||
HandleUserinfo(w http.ResponseWriter, r *http.Request)
|
||||
//HandleEndSession(w http.ResponseWriter, r *http.Request)
|
||||
HandleKeys(w http.ResponseWriter, r *http.Request)
|
||||
HttpHandler() http.Handler
|
||||
Authorizer
|
||||
SessionEnder
|
||||
Signer() Signer
|
||||
Probes() []ProbesFn
|
||||
|
@ -47,12 +41,12 @@ func CreateRouter(o OpenIDProvider, interceptors ...HttpInterceptor) *mux.Router
|
|||
router.HandleFunc(healthzEndpoint, Healthz)
|
||||
router.HandleFunc(readinessEndpoint, Ready(o.Probes()))
|
||||
router.HandleFunc(oidc.DiscoveryEndpoint, DiscoveryHandler(o, o.Signer()))
|
||||
router.Handle(o.AuthorizationEndpoint().Relative(), intercept(o.HandleAuthorize))
|
||||
router.Handle(o.AuthorizationEndpoint().Relative()+"/{id}", intercept(o.HandleAuthorizeCallback))
|
||||
router.Handle(o.TokenEndpoint().Relative(), intercept(o.HandleExchange))
|
||||
router.HandleFunc(o.UserinfoEndpoint().Relative(), o.HandleUserinfo)
|
||||
router.Handle(o.EndSessionEndpoint().Relative(), intercept(EndSessionHandler(o)))
|
||||
router.HandleFunc(o.KeysEndpoint().Relative(), o.HandleKeys)
|
||||
router.Handle(o.AuthorizationEndpoint().Relative(), intercept(authorizeHandler(o)))
|
||||
router.Handle(o.AuthorizationEndpoint().Relative()+"/{id}", intercept(authorizeCallbackHandler(o)))
|
||||
router.Handle(o.TokenEndpoint().Relative(), intercept(tokenHandler(o)))
|
||||
router.HandleFunc(o.UserinfoEndpoint().Relative(), userinfoHandler(o))
|
||||
router.Handle(o.EndSessionEndpoint().Relative(), intercept(endSessionHandler(o)))
|
||||
router.HandleFunc(o.KeysEndpoint().Relative(), keysHandler(o))
|
||||
return router
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ type SessionEnder interface {
|
|||
DefaultLogoutRedirectURI() string
|
||||
}
|
||||
|
||||
func EndSessionHandler(ender SessionEnder) func(http.ResponseWriter, *http.Request) {
|
||||
func endSessionHandler(ender SessionEnder) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
EndSession(w, r, ender)
|
||||
}
|
||||
|
|
|
@ -27,6 +27,26 @@ type VerifyExchanger interface {
|
|||
ClientJWTVerifier() rp.Verifier
|
||||
}
|
||||
|
||||
func tokenHandler(exchanger Exchanger) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.FormValue("grant_type") {
|
||||
case string(oidc.GrantTypeCode):
|
||||
CodeExchange(w, r, exchanger)
|
||||
return
|
||||
case string(oidc.GrantTypeBearer):
|
||||
JWTExchange(w, r, exchanger)
|
||||
return
|
||||
case "excahnge":
|
||||
TokenExchange(w, r, exchanger)
|
||||
case "":
|
||||
RequestError(w, r, ErrInvalidRequest("grant_type missing"))
|
||||
return
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CodeExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
||||
tokenReq, err := ParseAccessTokenRequest(r, exchanger.Decoder())
|
||||
if err != nil {
|
||||
|
|
|
@ -15,6 +15,12 @@ type UserinfoProvider interface {
|
|||
Storage() Storage
|
||||
}
|
||||
|
||||
func userinfoHandler(userinfoProvider UserinfoProvider) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
Userinfo(w, r, userinfoProvider)
|
||||
}
|
||||
}
|
||||
|
||||
func Userinfo(w http.ResponseWriter, r *http.Request, userinfoProvider UserinfoProvider) {
|
||||
accessToken, err := getAccessToken(r, userinfoProvider.Decoder())
|
||||
if err != nil {
|
||||
|
|
73
pkg/op/verifier.go
Normal file
73
pkg/op/verifier.go
Normal file
|
@ -0,0 +1,73 @@
|
|||
package op
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
)
|
||||
|
||||
type IDTokenHintVerifier interface {
|
||||
}
|
||||
|
||||
//VerifyIDToken validates the id token according to
|
||||
//https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
|
||||
func VerifyIDTokenHint(ctx context.Context, token string, v IDTokenHintVerifier) (*oidc.IDTokenClaims, error) {
|
||||
claims := new(oidc.IDTokenClaims)
|
||||
|
||||
decrypted, err := oidc.DecryptToken(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload, err := oidc.ParseToken(decrypted, claims)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//2, check issuer (exact match)
|
||||
if err := oidc.CheckIssuer(claims.GetIssuer(), v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//3. check aud (aud must contain client_id, all aud strings must be allowed)
|
||||
if err = oidc.CheckAudience(claims.GetAudience(), v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = oidc.CheckAuthorizedParty(claims.GetAudience(), claims.GetAuthorizedParty(), v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//6. check signature by keys
|
||||
//7. check alg default is rs256
|
||||
//8. check if alg is mac based (hs...) -> audience contains client_id. for validation use utf-8 representation of your client_secret
|
||||
if err = oidc.CheckSignature(ctx, decrypted, payload, claims, v.SupportedSignAlgs(), v.KeySet()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//9. check exp before now
|
||||
if err = oidc.CheckExpiration(claims.GetExpiration(), v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//10. check iat duration is optional (can be checked)
|
||||
if err = oidc.CheckIssuedAt(claims.GetIssuedAt(), v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/*
|
||||
//11. check nonce (check if optional possible) id_token.nonce == sentNonce
|
||||
if err = oidc.CheckNonce(claims.GetNonce()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*/
|
||||
|
||||
//12. if acr requested check acr
|
||||
if err = oidc.CheckAuthorizationContextClassReference(claims.GetAuthenticationContextClassReference(), v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//13. if auth_time requested check if auth_time is less than max age
|
||||
if err = oidc.CheckAuthTime(claims.GetAuthTime(), v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return claims, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue