|
5 | 5 | "crypto/rand" |
6 | 6 | "crypto/rsa" |
7 | 7 | "crypto/sha256" |
| 8 | + "encoding/base64" |
8 | 9 | "encoding/json" |
9 | 10 | "fmt" |
10 | 11 | "net/http" |
@@ -413,3 +414,55 @@ func TestAuthWithEmptyState(t *testing.T) { |
413 | 414 | require.NoError(t, err) |
414 | 415 | require.NotEmpty(t, tokenResult["access_token"]) |
415 | 416 | } |
| 417 | + |
| 418 | +func TestAccessTokenAudienceClaim(t *testing.T) { |
| 419 | + server, _, _ := setupTestServer(t) |
| 420 | + regResp := registerTestClient(t, server.URL) |
| 421 | + |
| 422 | + config := &oauth2.Config{ |
| 423 | + ClientID: regResp.ClientID, |
| 424 | + ClientSecret: regResp.ClientSecret, |
| 425 | + RedirectURL: "http://localhost:8080/callback", |
| 426 | + Scopes: []string{}, |
| 427 | + Endpoint: oauth2.Endpoint{ |
| 428 | + AuthURL: server.URL + AuthorizationEndpoint, |
| 429 | + TokenURL: server.URL + TokenEndpoint, |
| 430 | + }, |
| 431 | + } |
| 432 | + |
| 433 | + callbackURL := testAuthFlowWithURL(t, server.URL, config.AuthCodeURL("test-state")) |
| 434 | + code := callbackURL.Query().Get("code") |
| 435 | + |
| 436 | + tokenReq := url.Values{} |
| 437 | + tokenReq.Set("grant_type", "authorization_code") |
| 438 | + tokenReq.Set("code", code) |
| 439 | + tokenReq.Set("redirect_uri", "http://localhost:8080/callback") |
| 440 | + tokenReq.Set("client_id", regResp.ClientID) |
| 441 | + tokenReq.Set("client_secret", regResp.ClientSecret) |
| 442 | + |
| 443 | + tokenResp, err := http.PostForm(server.URL+TokenEndpoint, tokenReq) |
| 444 | + require.NoError(t, err) |
| 445 | + defer tokenResp.Body.Close() |
| 446 | + require.Equal(t, http.StatusOK, tokenResp.StatusCode) |
| 447 | + |
| 448 | + var tokenResult map[string]any |
| 449 | + err = json.NewDecoder(tokenResp.Body).Decode(&tokenResult) |
| 450 | + require.NoError(t, err) |
| 451 | + |
| 452 | + accessToken := tokenResult["access_token"].(string) |
| 453 | + |
| 454 | + // Decode JWT payload and verify aud claim contains the external URL |
| 455 | + parts := strings.Split(accessToken, ".") |
| 456 | + require.Len(t, parts, 3, "access token should be a JWT with 3 parts") |
| 457 | + |
| 458 | + payload, err := base64.RawURLEncoding.DecodeString(parts[1]) |
| 459 | + require.NoError(t, err) |
| 460 | + |
| 461 | + var claims map[string]any |
| 462 | + err = json.Unmarshal(payload, &claims) |
| 463 | + require.NoError(t, err) |
| 464 | + |
| 465 | + aud, ok := claims["aud"].([]any) |
| 466 | + require.True(t, ok, "aud claim should be present as an array") |
| 467 | + require.Contains(t, aud, "http://localhost:8080", "aud should contain the external URL") |
| 468 | +} |
0 commit comments