From 64631d5780c790fcf5bd76a6468f004cf1ea91ea Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Wed, 9 Dec 2020 14:53:39 -0800 Subject: [PATCH] token_handler_test.go: add even more test cases for refresh grant Signed-off-by: Margo Crawford --- internal/oidc/token/token_handler_test.go | 98 ++++++++++++++++++++++- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/internal/oidc/token/token_handler_test.go b/internal/oidc/token/token_handler_test.go index 883b5eb9..cd2d0d28 100644 --- a/internal/oidc/token/token_handler_test.go +++ b/internal/oidc/token/token_handler_test.go @@ -639,7 +639,7 @@ func TestTokenEndpointWhenAuthcodeIsUsedTwice(t *testing.T) { } type refreshRequestInputs struct { - modifyTokenRequest func(tokenRequest *http.Request, refreshToken string) + modifyTokenRequest func(tokenRequest *http.Request, refreshToken string, accessToken string) want tokenEndpointResponseExpectedValues } @@ -687,6 +687,72 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"offline_access"}, }}, }, + { + name: "when the refresh request adds a new scope to the list of requested scopes then it is ignored", + authcodeExchange: authcodeExchangeInputs{ + modifyAuthRequest: func(r *http.Request) { r.Form.Set("scope", "openid offline_access") }, + want: tokenEndpointResponseExpectedValues{ + wantStatus: http.StatusOK, + wantSuccessBodyFields: []string{"id_token", "refresh_token", "access_token", "token_type", "expires_in", "scope"}, + wantRequestedScopes: []string{"openid", "offline_access"}, + wantGrantedScopes: []string{"openid", "offline_access"}, + }, + }, + refreshRequest: refreshRequestInputs{ + modifyTokenRequest: func(r *http.Request, refreshToken string, accessToken string) { + r.Body = happyRefreshRequestBody(refreshToken).WithScope("openid some-other-scope-not-from-auth-request").ReadCloser() + }, + want: tokenEndpointResponseExpectedValues{ + wantStatus: http.StatusOK, + wantSuccessBodyFields: []string{"id_token", "refresh_token", "access_token", "token_type", "expires_in", "scope"}, + wantRequestedScopes: []string{"openid", "offline_access"}, + wantGrantedScopes: []string{"openid", "offline_access"}, + }}, + }, + { + name: "when the refresh request removes a scope which was originally granted from the list of requested scopes then it is ignored", + authcodeExchange: authcodeExchangeInputs{ + modifyAuthRequest: func(r *http.Request) { r.Form.Set("scope", "openid offline_access") }, + want: tokenEndpointResponseExpectedValues{ + wantStatus: http.StatusOK, + wantSuccessBodyFields: []string{"id_token", "refresh_token", "access_token", "token_type", "expires_in", "scope"}, + wantRequestedScopes: []string{"openid", "offline_access"}, + wantGrantedScopes: []string{"openid", "offline_access"}, + }, + }, + refreshRequest: refreshRequestInputs{ + modifyTokenRequest: func(r *http.Request, refreshToken string, accessToken string) { + r.Body = happyRefreshRequestBody(refreshToken).WithScope("").ReadCloser() // TODO FIX ME. WE NEED ANOTHER VALID SCOPE ON THIS CLIENT TO WRITE THIS TEST. + }, + want: tokenEndpointResponseExpectedValues{ + wantStatus: http.StatusOK, + wantSuccessBodyFields: []string{"id_token", "refresh_token", "access_token", "token_type", "expires_in", "scope"}, + wantRequestedScopes: []string{"openid", "offline_access"}, + wantGrantedScopes: []string{"openid", "offline_access"}, + }}, + }, + { + name: "when the refresh request does not include a scope param then it gets all the same scopes as the original authorization request", + authcodeExchange: authcodeExchangeInputs{ + modifyAuthRequest: func(r *http.Request) { r.Form.Set("scope", "openid offline_access") }, + want: tokenEndpointResponseExpectedValues{ + wantStatus: http.StatusOK, + wantSuccessBodyFields: []string{"id_token", "refresh_token", "access_token", "token_type", "expires_in", "scope"}, + wantRequestedScopes: []string{"openid", "offline_access"}, + wantGrantedScopes: []string{"openid", "offline_access"}, + }, + }, + refreshRequest: refreshRequestInputs{ + modifyTokenRequest: func(r *http.Request, refreshToken string, accessToken string) { + r.Body = happyRefreshRequestBody(refreshToken).WithScope("").ReadCloser() + }, + want: tokenEndpointResponseExpectedValues{ + wantStatus: http.StatusOK, + wantSuccessBodyFields: []string{"id_token", "refresh_token", "access_token", "token_type", "expires_in", "scope"}, + wantRequestedScopes: []string{"openid", "offline_access"}, + wantGrantedScopes: []string{"openid", "offline_access"}, + }}, + }, { name: "when a bad refresh token is sent in the refresh request", authcodeExchange: authcodeExchangeInputs{ @@ -699,7 +765,7 @@ func TestRefreshGrant(t *testing.T) { }, }, refreshRequest: refreshRequestInputs{ - modifyTokenRequest: func(r *http.Request, refreshToken string) { + modifyTokenRequest: func(r *http.Request, refreshToken string, accessToken string) { r.Body = happyRefreshRequestBody(refreshToken).WithRefreshToken("bad refresh token").ReadCloser() }, want: tokenEndpointResponseExpectedValues{ @@ -707,6 +773,26 @@ func TestRefreshGrant(t *testing.T) { wantErrorResponseBody: fositeInvalidAuthCodeErrorBody, }}, }, + { + name: "when the access token is sent as if it were a refresh token", + authcodeExchange: authcodeExchangeInputs{ + modifyAuthRequest: func(r *http.Request) { r.Form.Set("scope", "offline_access") }, + want: tokenEndpointResponseExpectedValues{ + wantStatus: http.StatusOK, + wantSuccessBodyFields: []string{"refresh_token", "access_token", "token_type", "expires_in", "scope"}, + wantRequestedScopes: []string{"offline_access"}, + wantGrantedScopes: []string{"offline_access"}, + }, + }, + refreshRequest: refreshRequestInputs{ + modifyTokenRequest: func(r *http.Request, refreshToken string, accessToken string) { + r.Body = happyRefreshRequestBody(refreshToken).WithRefreshToken(accessToken).ReadCloser() + }, + want: tokenEndpointResponseExpectedValues{ + wantStatus: http.StatusBadRequest, + wantErrorResponseBody: fositeInvalidAuthCodeErrorBody, + }}, + }, { name: "when the wrong client ID is included in the refresh request", authcodeExchange: authcodeExchangeInputs{ @@ -719,7 +805,7 @@ func TestRefreshGrant(t *testing.T) { }, }, refreshRequest: refreshRequestInputs{ - modifyTokenRequest: func(r *http.Request, refreshToken string) { + modifyTokenRequest: func(r *http.Request, refreshToken string, accessToken string) { r.Body = happyRefreshRequestBody(refreshToken).WithClientID("wrong-client-id").ReadCloser() }, want: tokenEndpointResponseExpectedValues{ @@ -750,7 +836,7 @@ func TestRefreshGrant(t *testing.T) { happyRefreshRequestBody(firstRefreshToken).ReadCloser()) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") if test.refreshRequest.modifyTokenRequest != nil { - test.refreshRequest.modifyTokenRequest(req, firstRefreshToken) + test.refreshRequest.modifyTokenRequest(req, firstRefreshToken, parsedAuthcodeExchangeResponseBody["access_token"].(string)) } refreshResponse := httptest.NewRecorder() @@ -983,6 +1069,10 @@ func (b body) WithAuthCode(code string) body { return b.with("code", code) } +func (b body) WithScope(scope string) body { + return b.with("scope", scope) +} + func (b body) WithRedirectURI(redirectURI string) body { return b.with("redirect_uri", redirectURI) }