Merge pull request #257 from mattmoyer/prefactoring-for-cli-request-audience
Prefactor before adding CLI "request audience" functionality.
This commit is contained in:
commit
66270fded0
@ -43,13 +43,12 @@ func (m *MockUpstreamOIDCIdentityProviderI) EXPECT() *MockUpstreamOIDCIdentityPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExchangeAuthcodeAndValidateTokens mocks base method
|
// ExchangeAuthcodeAndValidateTokens mocks base method
|
||||||
func (m *MockUpstreamOIDCIdentityProviderI) ExchangeAuthcodeAndValidateTokens(arg0 context.Context, arg1 string, arg2 pkce.Code, arg3 nonce.Nonce, arg4 string) (oidctypes.Token, map[string]interface{}, error) {
|
func (m *MockUpstreamOIDCIdentityProviderI) ExchangeAuthcodeAndValidateTokens(arg0 context.Context, arg1 string, arg2 pkce.Code, arg3 nonce.Nonce, arg4 string) (*oidctypes.Token, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ExchangeAuthcodeAndValidateTokens", arg0, arg1, arg2, arg3, arg4)
|
ret := m.ctrl.Call(m, "ExchangeAuthcodeAndValidateTokens", arg0, arg1, arg2, arg3, arg4)
|
||||||
ret0, _ := ret[0].(oidctypes.Token)
|
ret0, _ := ret[0].(*oidctypes.Token)
|
||||||
ret1, _ := ret[1].(map[string]interface{})
|
ret1, _ := ret[1].(error)
|
||||||
ret2, _ := ret[2].(error)
|
return ret0, ret1
|
||||||
return ret0, ret1, ret2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExchangeAuthcodeAndValidateTokens indicates an expected call of ExchangeAuthcodeAndValidateTokens
|
// ExchangeAuthcodeAndValidateTokens indicates an expected call of ExchangeAuthcodeAndValidateTokens
|
||||||
@ -143,13 +142,12 @@ func (mr *MockUpstreamOIDCIdentityProviderIMockRecorder) GetUsernameClaim() *gom
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateToken mocks base method
|
// ValidateToken mocks base method
|
||||||
func (m *MockUpstreamOIDCIdentityProviderI) ValidateToken(arg0 context.Context, arg1 *oauth2.Token, arg2 nonce.Nonce) (oidctypes.Token, map[string]interface{}, error) {
|
func (m *MockUpstreamOIDCIdentityProviderI) ValidateToken(arg0 context.Context, arg1 *oauth2.Token, arg2 nonce.Nonce) (*oidctypes.Token, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ValidateToken", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "ValidateToken", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].(oidctypes.Token)
|
ret0, _ := ret[0].(*oidctypes.Token)
|
||||||
ret1, _ := ret[1].(map[string]interface{})
|
ret1, _ := ret[1].(error)
|
||||||
ret2, _ := ret[2].(error)
|
return ret0, ret1
|
||||||
return ret0, ret1, ret2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateToken indicates an expected call of ValidateToken
|
// ValidateToken indicates an expected call of ValidateToken
|
||||||
|
@ -73,7 +73,7 @@ func NewHandler(
|
|||||||
// Grant the openid scope only if it was requested.
|
// Grant the openid scope only if it was requested.
|
||||||
grantOpenIDScopeIfRequested(authorizeRequester)
|
grantOpenIDScopeIfRequested(authorizeRequester)
|
||||||
|
|
||||||
_, idTokenClaims, err := upstreamIDPConfig.ExchangeAuthcodeAndValidateTokens(
|
token, err := upstreamIDPConfig.ExchangeAuthcodeAndValidateTokens(
|
||||||
r.Context(),
|
r.Context(),
|
||||||
authcode(r),
|
authcode(r),
|
||||||
state.PKCECode,
|
state.PKCECode,
|
||||||
@ -85,12 +85,12 @@ func NewHandler(
|
|||||||
return httperr.New(http.StatusBadGateway, "error exchanging and validating upstream tokens")
|
return httperr.New(http.StatusBadGateway, "error exchanging and validating upstream tokens")
|
||||||
}
|
}
|
||||||
|
|
||||||
username, err := getUsernameFromUpstreamIDToken(upstreamIDPConfig, idTokenClaims)
|
username, err := getUsernameFromUpstreamIDToken(upstreamIDPConfig, token.IDToken.Claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
groups, err := getGroupsFromUpstreamIDToken(upstreamIDPConfig, idTokenClaims)
|
groups, err := getGroupsFromUpstreamIDToken(upstreamIDPConfig, token.IDToken.Claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -682,8 +682,11 @@ func (u *upstreamOIDCIdentityProviderBuilder) Build() oidctestutil.TestUpstreamO
|
|||||||
UsernameClaim: u.usernameClaim,
|
UsernameClaim: u.usernameClaim,
|
||||||
GroupsClaim: u.groupsClaim,
|
GroupsClaim: u.groupsClaim,
|
||||||
Scopes: []string{"scope1", "scope2"},
|
Scopes: []string{"scope1", "scope2"},
|
||||||
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (oidctypes.Token, map[string]interface{}, error) {
|
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (*oidctypes.Token, error) {
|
||||||
return oidctypes.Token{}, u.idToken, u.authcodeExchangeErr
|
if u.authcodeExchangeErr != nil {
|
||||||
|
return nil, u.authcodeExchangeErr
|
||||||
|
}
|
||||||
|
return &oidctypes.Token{IDToken: &oidctypes.IDToken{Claims: u.idToken}}, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ type TestUpstreamOIDCIdentityProvider struct {
|
|||||||
authcode string,
|
authcode string,
|
||||||
pkceCodeVerifier pkce.Code,
|
pkceCodeVerifier pkce.Code,
|
||||||
expectedIDTokenNonce nonce.Nonce,
|
expectedIDTokenNonce nonce.Nonce,
|
||||||
) (oidctypes.Token, map[string]interface{}, error)
|
) (*oidctypes.Token, error)
|
||||||
|
|
||||||
exchangeAuthcodeAndValidateTokensCallCount int
|
exchangeAuthcodeAndValidateTokensCallCount int
|
||||||
exchangeAuthcodeAndValidateTokensArgs []*ExchangeAuthcodeAndValidateTokenArgs
|
exchangeAuthcodeAndValidateTokensArgs []*ExchangeAuthcodeAndValidateTokenArgs
|
||||||
@ -75,7 +75,7 @@ func (u *TestUpstreamOIDCIdentityProvider) ExchangeAuthcodeAndValidateTokens(
|
|||||||
pkceCodeVerifier pkce.Code,
|
pkceCodeVerifier pkce.Code,
|
||||||
expectedIDTokenNonce nonce.Nonce,
|
expectedIDTokenNonce nonce.Nonce,
|
||||||
redirectURI string,
|
redirectURI string,
|
||||||
) (oidctypes.Token, map[string]interface{}, error) {
|
) (*oidctypes.Token, error) {
|
||||||
if u.exchangeAuthcodeAndValidateTokensArgs == nil {
|
if u.exchangeAuthcodeAndValidateTokensArgs == nil {
|
||||||
u.exchangeAuthcodeAndValidateTokensArgs = make([]*ExchangeAuthcodeAndValidateTokenArgs, 0)
|
u.exchangeAuthcodeAndValidateTokensArgs = make([]*ExchangeAuthcodeAndValidateTokenArgs, 0)
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ func (u *TestUpstreamOIDCIdentityProvider) ExchangeAuthcodeAndValidateTokensArgs
|
|||||||
return u.exchangeAuthcodeAndValidateTokensArgs[call]
|
return u.exchangeAuthcodeAndValidateTokensArgs[call]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *TestUpstreamOIDCIdentityProvider) ValidateToken(ctx context.Context, tok *oauth2.Token, expectedIDTokenNonce nonce.Nonce) (oidctypes.Token, map[string]interface{}, error) {
|
func (u *TestUpstreamOIDCIdentityProvider) ValidateToken(_ context.Context, _ *oauth2.Token, _ nonce.Nonce) (*oidctypes.Token, error) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +43,9 @@ type UpstreamOIDCIdentityProviderI interface {
|
|||||||
pkceCodeVerifier pkce.Code,
|
pkceCodeVerifier pkce.Code,
|
||||||
expectedIDTokenNonce nonce.Nonce,
|
expectedIDTokenNonce nonce.Nonce,
|
||||||
redirectURI string,
|
redirectURI string,
|
||||||
) (tokens oidctypes.Token, parsedIDTokenClaims map[string]interface{}, err error)
|
) (*oidctypes.Token, error)
|
||||||
|
|
||||||
ValidateToken(ctx context.Context, tok *oauth2.Token, expectedIDTokenNonce nonce.Nonce) (oidctypes.Token, map[string]interface{}, error)
|
ValidateToken(ctx context.Context, tok *oauth2.Token, expectedIDTokenNonce nonce.Nonce) (*oidctypes.Token, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DynamicUpstreamIDPProvider interface {
|
type DynamicUpstreamIDPProvider interface {
|
||||||
|
@ -172,15 +172,17 @@ func TestManager(t *testing.T) {
|
|||||||
ClientID: "test-client-id",
|
ClientID: "test-client-id",
|
||||||
AuthorizationURL: *parsedUpstreamIDPAuthorizationURL,
|
AuthorizationURL: *parsedUpstreamIDPAuthorizationURL,
|
||||||
Scopes: []string{"test-scope"},
|
Scopes: []string{"test-scope"},
|
||||||
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (oidctypes.Token, map[string]interface{}, error) {
|
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (*oidctypes.Token, error) {
|
||||||
return oidctypes.Token{},
|
return &oidctypes.Token{
|
||||||
map[string]interface{}{
|
IDToken: &oidctypes.IDToken{
|
||||||
|
Claims: map[string]interface{}{
|
||||||
"iss": "https://some-issuer.com",
|
"iss": "https://some-issuer.com",
|
||||||
"sub": "some-subject",
|
"sub": "some-subject",
|
||||||
"username": "test-username",
|
"username": "test-username",
|
||||||
"groups": "test-group1",
|
"groups": "test-group1",
|
||||||
},
|
},
|
||||||
nil
|
},
|
||||||
|
}, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func (p *ProviderConfig) GetGroupsClaim() string {
|
|||||||
return p.GroupsClaim
|
return p.GroupsClaim
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProviderConfig) ExchangeAuthcodeAndValidateTokens(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce, redirectURI string) (oidctypes.Token, map[string]interface{}, error) {
|
func (p *ProviderConfig) ExchangeAuthcodeAndValidateTokens(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce, redirectURI string) (*oidctypes.Token, error) {
|
||||||
tok, err := p.Config.Exchange(
|
tok, err := p.Config.Exchange(
|
||||||
oidc.ClientContext(ctx, p.Client),
|
oidc.ClientContext(ctx, p.Client),
|
||||||
authcode,
|
authcode,
|
||||||
@ -69,38 +69,38 @@ func (p *ProviderConfig) ExchangeAuthcodeAndValidateTokens(ctx context.Context,
|
|||||||
oauth2.SetAuthURLParam("redirect_uri", redirectURI),
|
oauth2.SetAuthURLParam("redirect_uri", redirectURI),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oidctypes.Token{}, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.ValidateToken(ctx, tok, expectedIDTokenNonce)
|
return p.ValidateToken(ctx, tok, expectedIDTokenNonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProviderConfig) ValidateToken(ctx context.Context, tok *oauth2.Token, expectedIDTokenNonce nonce.Nonce) (oidctypes.Token, map[string]interface{}, error) {
|
func (p *ProviderConfig) ValidateToken(ctx context.Context, tok *oauth2.Token, expectedIDTokenNonce nonce.Nonce) (*oidctypes.Token, error) {
|
||||||
idTok, hasIDTok := tok.Extra("id_token").(string)
|
idTok, hasIDTok := tok.Extra("id_token").(string)
|
||||||
if !hasIDTok {
|
if !hasIDTok {
|
||||||
return oidctypes.Token{}, nil, httperr.New(http.StatusBadRequest, "received response missing ID token")
|
return nil, httperr.New(http.StatusBadRequest, "received response missing ID token")
|
||||||
}
|
}
|
||||||
validated, err := p.Provider.Verifier(&oidc.Config{ClientID: p.GetClientID()}).Verify(oidc.ClientContext(ctx, p.Client), idTok)
|
validated, err := p.Provider.Verifier(&oidc.Config{ClientID: p.GetClientID()}).Verify(oidc.ClientContext(ctx, p.Client), idTok)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oidctypes.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received invalid ID token", err)
|
return nil, httperr.Wrap(http.StatusBadRequest, "received invalid ID token", err)
|
||||||
}
|
}
|
||||||
if validated.AccessTokenHash != "" {
|
if validated.AccessTokenHash != "" {
|
||||||
if err := validated.VerifyAccessToken(tok.AccessToken); err != nil {
|
if err := validated.VerifyAccessToken(tok.AccessToken); err != nil {
|
||||||
return oidctypes.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received invalid ID token", err)
|
return nil, httperr.Wrap(http.StatusBadRequest, "received invalid ID token", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if expectedIDTokenNonce != "" {
|
if expectedIDTokenNonce != "" {
|
||||||
if err := expectedIDTokenNonce.Validate(validated); err != nil {
|
if err := expectedIDTokenNonce.Validate(validated); err != nil {
|
||||||
return oidctypes.Token{}, nil, httperr.Wrap(http.StatusBadRequest, "received ID token with invalid nonce", err)
|
return nil, httperr.Wrap(http.StatusBadRequest, "received ID token with invalid nonce", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var validatedClaims map[string]interface{}
|
var validatedClaims map[string]interface{}
|
||||||
if err := validated.Claims(&validatedClaims); err != nil {
|
if err := validated.Claims(&validatedClaims); err != nil {
|
||||||
return oidctypes.Token{}, nil, httperr.Wrap(http.StatusInternalServerError, "could not unmarshal claims", err)
|
return nil, httperr.Wrap(http.StatusInternalServerError, "could not unmarshal claims", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return oidctypes.Token{
|
return &oidctypes.Token{
|
||||||
AccessToken: &oidctypes.AccessToken{
|
AccessToken: &oidctypes.AccessToken{
|
||||||
Token: tok.AccessToken,
|
Token: tok.AccessToken,
|
||||||
Type: tok.TokenType,
|
Type: tok.TokenType,
|
||||||
@ -112,6 +112,7 @@ func (p *ProviderConfig) ValidateToken(ctx context.Context, tok *oauth2.Token, e
|
|||||||
IDToken: &oidctypes.IDToken{
|
IDToken: &oidctypes.IDToken{
|
||||||
Token: idTok,
|
Token: idTok,
|
||||||
Expiry: metav1.NewTime(validated.Expiry),
|
Expiry: metav1.NewTime(validated.Expiry),
|
||||||
|
Claims: validatedClaims,
|
||||||
},
|
},
|
||||||
}, validatedClaims, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,6 @@ func TestProviderConfig(t *testing.T) {
|
|||||||
returnIDTok string
|
returnIDTok string
|
||||||
wantErr string
|
wantErr string
|
||||||
wantToken oidctypes.Token
|
wantToken oidctypes.Token
|
||||||
wantClaims map[string]interface{}
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "exchange fails with network error",
|
name: "exchange fails with network error",
|
||||||
@ -110,6 +109,14 @@ func TestProviderConfig(t *testing.T) {
|
|||||||
IDToken: &oidctypes.IDToken{
|
IDToken: &oidctypes.IDToken{
|
||||||
Token: invalidNonceIDToken,
|
Token: invalidNonceIDToken,
|
||||||
Expiry: metav1.Time{},
|
Expiry: metav1.Time{},
|
||||||
|
Claims: map[string]interface{}{
|
||||||
|
"aud": "test-client-id",
|
||||||
|
"iat": 1.602283741e+09,
|
||||||
|
"jti": "test-jti",
|
||||||
|
"nbf": 1.602283741e+09,
|
||||||
|
"nonce": "invalid-nonce",
|
||||||
|
"sub": "test-user",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -128,11 +135,16 @@ func TestProviderConfig(t *testing.T) {
|
|||||||
IDToken: &oidctypes.IDToken{
|
IDToken: &oidctypes.IDToken{
|
||||||
Token: validIDToken,
|
Token: validIDToken,
|
||||||
Expiry: metav1.Time{},
|
Expiry: metav1.Time{},
|
||||||
},
|
Claims: map[string]interface{}{
|
||||||
},
|
|
||||||
wantClaims: map[string]interface{}{
|
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
"bat": "baz",
|
"bat": "baz",
|
||||||
|
"aud": "test-client-id",
|
||||||
|
"iat": 1.606768593e+09,
|
||||||
|
"jti": "test-jti",
|
||||||
|
"nbf": 1.606768593e+09,
|
||||||
|
"sub": "test-user",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -181,19 +193,14 @@ func TestProviderConfig(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
tok, claims, err := p.ExchangeAuthcodeAndValidateTokens(ctx, tt.authCode, "test-pkce", tt.expectNonce, "https://example.com/callback")
|
tok, err := p.ExchangeAuthcodeAndValidateTokens(ctx, tt.authCode, "test-pkce", tt.expectNonce, "https://example.com/callback")
|
||||||
if tt.wantErr != "" {
|
if tt.wantErr != "" {
|
||||||
require.EqualError(t, err, tt.wantErr)
|
require.EqualError(t, err, tt.wantErr)
|
||||||
require.Equal(t, oidctypes.Token{}, tok)
|
require.Nil(t, tok)
|
||||||
require.Nil(t, claims)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, tt.wantToken, tok)
|
require.Equal(t, &tt.wantToken, tok)
|
||||||
|
|
||||||
for k, v := range tt.wantClaims {
|
|
||||||
require.Equal(t, v, claims[k])
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,13 @@ var validSession = sessionCache{
|
|||||||
IDToken: &oidctypes.IDToken{
|
IDToken: &oidctypes.IDToken{
|
||||||
Token: "test-id-token",
|
Token: "test-id-token",
|
||||||
Expiry: metav1.NewTime(time.Date(2020, 10, 20, 19, 42, 07, 0, time.UTC).Local()),
|
Expiry: metav1.NewTime(time.Date(2020, 10, 20, 19, 42, 07, 0, time.UTC).Local()),
|
||||||
|
Claims: map[string]interface{}{
|
||||||
|
"foo": "bar",
|
||||||
|
"nested": map[string]interface{}{
|
||||||
|
"key1": "value1",
|
||||||
|
"key2": "value2",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
RefreshToken: &oidctypes.RefreshToken{
|
RefreshToken: &oidctypes.RefreshToken{
|
||||||
Token: "test-refresh-token",
|
Token: "test-refresh-token",
|
||||||
|
@ -20,5 +20,10 @@ sessions:
|
|||||||
id:
|
id:
|
||||||
expiryTimestamp: "2020-10-20T19:42:07Z"
|
expiryTimestamp: "2020-10-20T19:42:07Z"
|
||||||
token: test-id-token
|
token: test-id-token
|
||||||
|
claims:
|
||||||
|
foo: bar
|
||||||
|
nested:
|
||||||
|
key1: value1
|
||||||
|
key2: value2
|
||||||
refresh:
|
refresh:
|
||||||
token: test-refresh-token
|
token: test-refresh-token
|
||||||
|
@ -295,11 +295,7 @@ func (h *handlerState) handleRefresh(ctx context.Context, refreshToken *oidctype
|
|||||||
|
|
||||||
// The spec is not 100% clear about whether an ID token from the refresh flow should include a nonce, and at least
|
// The spec is not 100% clear about whether an ID token from the refresh flow should include a nonce, and at least
|
||||||
// some providers do not include one, so we skip the nonce validation here (but not other validations).
|
// some providers do not include one, so we skip the nonce validation here (but not other validations).
|
||||||
token, _, err := h.getProvider(h.oauth2Config, h.provider, h.httpClient).ValidateToken(ctx, refreshed, "")
|
return h.getProvider(h.oauth2Config, h.provider, h.httpClient).ValidateToken(ctx, refreshed, "")
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &token, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handlerState) handleAuthCodeCallback(w http.ResponseWriter, r *http.Request) (err error) {
|
func (h *handlerState) handleAuthCodeCallback(w http.ResponseWriter, r *http.Request) (err error) {
|
||||||
@ -328,7 +324,7 @@ func (h *handlerState) handleAuthCodeCallback(w http.ResponseWriter, r *http.Req
|
|||||||
|
|
||||||
// Exchange the authorization code for access, ID, and refresh tokens and perform required
|
// Exchange the authorization code for access, ID, and refresh tokens and perform required
|
||||||
// validations on the returned ID token.
|
// validations on the returned ID token.
|
||||||
token, _, err := h.getProvider(h.oauth2Config, h.provider, h.httpClient).
|
token, err := h.getProvider(h.oauth2Config, h.provider, h.httpClient).
|
||||||
ExchangeAuthcodeAndValidateTokens(
|
ExchangeAuthcodeAndValidateTokens(
|
||||||
r.Context(),
|
r.Context(),
|
||||||
params.Get("code"),
|
params.Get("code"),
|
||||||
@ -340,7 +336,7 @@ func (h *handlerState) handleAuthCodeCallback(w http.ResponseWriter, r *http.Req
|
|||||||
return httperr.Wrap(http.StatusBadRequest, "could not complete code exchange", err)
|
return httperr.Wrap(http.StatusBadRequest, "could not complete code exchange", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.callbacks <- callbackResult{token: &token}
|
h.callbacks <- callbackResult{token: token}
|
||||||
_, _ = w.Write([]byte("you have been logged in and may now close this tab"))
|
_, _ = w.Write([]byte("you have been logged in and may now close this tab"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ func TestLogin(t *testing.T) {
|
|||||||
mock := mockUpstream(t)
|
mock := mockUpstream(t)
|
||||||
mock.EXPECT().
|
mock.EXPECT().
|
||||||
ValidateToken(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce("")).
|
ValidateToken(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce("")).
|
||||||
Return(testToken, nil, nil)
|
Return(&testToken, nil)
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ func TestLogin(t *testing.T) {
|
|||||||
mock := mockUpstream(t)
|
mock := mockUpstream(t)
|
||||||
mock.EXPECT().
|
mock.EXPECT().
|
||||||
ValidateToken(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce("")).
|
ValidateToken(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce("")).
|
||||||
Return(oidctypes.Token{}, nil, fmt.Errorf("some validation error"))
|
Return(nil, fmt.Errorf("some validation error"))
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,7 +529,7 @@ func TestHandleAuthCodeCallback(t *testing.T) {
|
|||||||
mock := mockUpstream(t)
|
mock := mockUpstream(t)
|
||||||
mock.EXPECT().
|
mock.EXPECT().
|
||||||
ExchangeAuthcodeAndValidateTokens(gomock.Any(), "invalid", pkce.Code("test-pkce"), nonce.Nonce("test-nonce"), testRedirectURI).
|
ExchangeAuthcodeAndValidateTokens(gomock.Any(), "invalid", pkce.Code("test-pkce"), nonce.Nonce("test-nonce"), testRedirectURI).
|
||||||
Return(oidctypes.Token{}, nil, fmt.Errorf("some exchange error"))
|
Return(nil, fmt.Errorf("some exchange error"))
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -546,7 +546,7 @@ func TestHandleAuthCodeCallback(t *testing.T) {
|
|||||||
mock := mockUpstream(t)
|
mock := mockUpstream(t)
|
||||||
mock.EXPECT().
|
mock.EXPECT().
|
||||||
ExchangeAuthcodeAndValidateTokens(gomock.Any(), "valid", pkce.Code("test-pkce"), nonce.Nonce("test-nonce"), testRedirectURI).
|
ExchangeAuthcodeAndValidateTokens(gomock.Any(), "valid", pkce.Code("test-pkce"), nonce.Nonce("test-nonce"), testRedirectURI).
|
||||||
Return(oidctypes.Token{IDToken: &oidctypes.IDToken{Token: "test-id-token"}}, nil, nil)
|
Return(&oidctypes.Token{IDToken: &oidctypes.IDToken{Token: "test-id-token"}}, nil)
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -31,6 +31,9 @@ type IDToken struct {
|
|||||||
|
|
||||||
// Expiry is the optional expiration time of the ID token.
|
// Expiry is the optional expiration time of the ID token.
|
||||||
Expiry v1.Time `json:"expiryTimestamp,omitempty"`
|
Expiry v1.Time `json:"expiryTimestamp,omitempty"`
|
||||||
|
|
||||||
|
// Claims are the claims expressed by the Token.
|
||||||
|
Claims map[string]interface{} `json:"claims,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Token contains the elements of an OIDC session.
|
// Token contains the elements of an OIDC session.
|
||||||
|
Loading…
Reference in New Issue
Block a user