WIP implementing TokenExchangeHandler methods

Signed-off-by: Margo Crawford <margaretc@vmware.com>
This commit is contained in:
Matt Moyer 2020-12-08 10:17:03 -08:00 committed by Margo Crawford
parent e5ecaf01a0
commit afbef23a51
2 changed files with 42 additions and 2 deletions

View File

@ -83,7 +83,7 @@ func PinnipedCLIOIDCClient() *fosite.DefaultOpenIDConnectClient {
Public: true, Public: true,
RedirectURIs: []string{"http://127.0.0.1/callback"}, RedirectURIs: []string{"http://127.0.0.1/callback"},
ResponseTypes: []string{"code"}, ResponseTypes: []string{"code"},
GrantTypes: []string{"authorization_code", "token_exchange"}, GrantTypes: []string{"authorization_code", "urn:ietf:params:oauth:grant-type:token-exchange"},
Scopes: []string{"openid", "profile", "email"}, Scopes: []string{"openid", "profile", "email"},
}, },
TokenEndpointAuthMethod: "none", TokenEndpointAuthMethod: "none",
@ -124,6 +124,7 @@ func FositeOauth2Helper(
OpenIDConnectTokenStrategy: newDynamicOpenIDConnectECDSAStrategy(oauthConfig, jwksProvider), OpenIDConnectTokenStrategy: newDynamicOpenIDConnectECDSAStrategy(oauthConfig, jwksProvider),
}, },
nil, // hasher, defaults to using BCrypt when nil. Used for hashing client secrets. nil, // hasher, defaults to using BCrypt when nil. Used for hashing client secrets.
TokenExchangeFactory,
compose.OAuth2AuthorizeExplicitFactory, compose.OAuth2AuthorizeExplicitFactory,
// compose.OAuth2RefreshTokenGrantFactory, // compose.OAuth2RefreshTokenGrantFactory,
compose.OpenIDConnectExplicitFactory, compose.OpenIDConnectExplicitFactory,

View File

@ -3,21 +3,60 @@ package oidc
import ( import (
"context" "context"
"github.com/ory/fosite/handler/oauth2"
"github.com/ory/fosite/handler/openid"
"github.com/pkg/errors"
"github.com/ory/fosite" "github.com/ory/fosite"
"github.com/ory/fosite/compose" "github.com/ory/fosite/compose"
) )
func TokenExchangeFactory(config *compose.Config, storage interface{}, strategy interface{}) interface{} { func TokenExchangeFactory(config *compose.Config, storage interface{}, strategy interface{}) interface{} {
return &TokenExchangeHandler{} return &TokenExchangeHandler{
strategy.(openid.OpenIDConnectTokenStrategy),
strategy.(oauth2.AccessTokenStrategy),
storage.(oauth2.AccessTokenStorage),
}
} }
type TokenExchangeHandler struct { type TokenExchangeHandler struct {
idTokenStrategy openid.OpenIDConnectTokenStrategy
accessTokenStrategy oauth2.AccessTokenStrategy
accessTokenStorage oauth2.AccessTokenStorage
} }
func (t *TokenExchangeHandler) HandleTokenEndpointRequest(ctx context.Context, requester fosite.AccessRequester) error { func (t *TokenExchangeHandler) HandleTokenEndpointRequest(ctx context.Context, requester fosite.AccessRequester) error {
if !(requester.GetGrantTypes().ExactOne("urn:ietf:params:oauth:grant-type:token-exchange")) {
return errors.WithStack(fosite.ErrUnknownRequest)
}
return nil return nil
} }
func (t *TokenExchangeHandler) PopulateTokenEndpointResponse(ctx context.Context, requester fosite.AccessRequester, responder fosite.AccessResponder) error { func (t *TokenExchangeHandler) PopulateTokenEndpointResponse(ctx context.Context, requester fosite.AccessRequester, responder fosite.AccessResponder) error {
params := requester.GetRequestForm()
accessToken := params.Get("subject_token")
if err := t.accessTokenStrategy.ValidateAccessToken(ctx, requester, accessToken); err != nil {
return errors.WithStack(err)
}
signature := t.accessTokenStrategy.AccessTokenSignature(accessToken)
accessTokenSession, err := t.accessTokenStorage.GetAccessTokenSession(ctx, signature, requester.GetSession())
if err != nil {
return errors.WithStack(err)
}
if !accessTokenSession.GetGrantedScopes().Has("pinniped.sts.unrestricted") {
return errors.WithStack(fosite.ErrScopeNotGranted)
}
// TODO check the other requester fields
scopedDownRequester := fosite.NewAccessRequest(requester.GetSession())
scopedDownRequester.GrantedAudience = []string{params.Get("audience")}
newToken, err := t.idTokenStrategy.GenerateIDToken(ctx, scopedDownRequester)
if err != nil {
return errors.WithStack(err)
}
responder.SetAccessToken(newToken)
responder.SetTokenType("N_A")
responder.SetExtra("issued_token_type", "urn:ietf:params:oauth:token-type:jwt")
return nil return nil
} }