Skip to content

Commit 5db1fb7

Browse files
authored
Merge pull request #304 from ory/master
[pull] master from ory:master
2 parents e63c360 + d389fd0 commit 5db1fb7

File tree

7 files changed

+306
-7
lines changed

7 files changed

+306
-7
lines changed

consent/helper.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
package consent
55

66
import (
7+
"net/url"
8+
"strings"
9+
710
"github.com/ory/fosite"
811
"github.com/ory/hydra/v2/client"
912
"github.com/ory/hydra/v2/flow"
@@ -38,3 +41,18 @@ func matchScopes(scopeStrategy fosite.ScopeStrategy, previousConsent []flow.Acce
3841

3942
return nil
4043
}
44+
45+
func caseInsensitiveFilterParam(q url.Values, key string) url.Values {
46+
query := url.Values{}
47+
key = strings.ToLower(key)
48+
for k, vs := range q {
49+
if key == strings.ToLower(k) {
50+
query.Set(k, "****")
51+
} else {
52+
for _, v := range vs {
53+
query.Add(k, v)
54+
}
55+
}
56+
}
57+
return query
58+
}

consent/helper_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"net/http"
99
"net/http/httptest"
10+
"net/url"
1011
"testing"
1112
"time"
1213

@@ -421,3 +422,42 @@ func TestCreateCsrfSession(t *testing.T) {
421422
})
422423
}
423424
}
425+
426+
func TestCaseInsensitiveFilterParam(t *testing.T) {
427+
for k, tc := range []struct {
428+
requestedQuery string
429+
key string
430+
431+
expectedQuery url.Values
432+
}{
433+
{
434+
requestedQuery: "key=value",
435+
key: "key2",
436+
expectedQuery: url.Values{"key": []string{"value"}},
437+
},
438+
{
439+
requestedQuery: "KeY=value",
440+
key: "key",
441+
expectedQuery: url.Values{"KeY": []string{"****"}},
442+
},
443+
{
444+
requestedQuery: "KeY=value",
445+
key: "kEy",
446+
expectedQuery: url.Values{"KeY": []string{"****"}},
447+
},
448+
{
449+
requestedQuery: "key=value&KEY2=value2",
450+
key: "key2",
451+
expectedQuery: url.Values{"key": []string{"value"}, "KEY2": []string{"****"}},
452+
},
453+
} {
454+
t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) {
455+
query, err := url.ParseQuery(tc.requestedQuery)
456+
assert.NoError(t, err)
457+
458+
q := caseInsensitiveFilterParam(query, tc.key)
459+
460+
assert.Equal(t, tc.expectedQuery, q)
461+
})
462+
}
463+
}

consent/strategy_default.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,9 +1298,7 @@ func (s *DefaultStrategy) forwardDeviceRequest(ctx context.Context, w http.Respo
12981298
iu := s.getDeviceVerificationPath(ctx)
12991299
// We don't want the user_code persisted in the database
13001300
q := r.URL.Query()
1301-
if q.Has("user_code") {
1302-
q.Set("user_code", "****")
1303-
}
1301+
q = caseInsensitiveFilterParam(q, "user_code")
13041302
iu.RawQuery = q.Encode()
13051303

13061304
f, err := s.r.ConsentManager().CreateDeviceUserAuthRequest(
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
"authorization_endpoint": "http://hydra.localhost/oauth2/auth",
3+
"backchannel_logout_session_supported": true,
4+
"backchannel_logout_supported": true,
5+
"claims_parameter_supported": false,
6+
"claims_supported": [
7+
"sub"
8+
],
9+
"code_challenge_methods_supported": [
10+
"plain",
11+
"S256"
12+
],
13+
"credentials_endpoint_draft_00": "http://hydra.localhost/credentials",
14+
"credentials_supported_draft_00": [
15+
{
16+
"cryptographic_binding_methods_supported": [
17+
"jwk"
18+
],
19+
"cryptographic_suites_supported": [
20+
"PS256",
21+
"RS256",
22+
"ES256",
23+
"PS384",
24+
"RS384",
25+
"ES384",
26+
"PS512",
27+
"RS512",
28+
"ES512",
29+
"EdDSA"
30+
],
31+
"format": "jwt_vc_json",
32+
"types": [
33+
"VerifiableCredential",
34+
"UserInfoCredential"
35+
]
36+
}
37+
],
38+
"device_authorization_endpoint": "http://hydra.localhost/oauth2/device/auth",
39+
"end_session_endpoint": "http://hydra.localhost/oauth2/sessions/logout",
40+
"frontchannel_logout_session_supported": true,
41+
"frontchannel_logout_supported": true,
42+
"grant_types_supported": [
43+
"authorization_code",
44+
"implicit",
45+
"client_credentials",
46+
"refresh_token",
47+
"urn:ietf:params:oauth:grant-type:device_code"
48+
],
49+
"id_token_signed_response_alg": [
50+
"RS256"
51+
],
52+
"id_token_signing_alg_values_supported": [
53+
"RS256"
54+
],
55+
"issuer": "http://hydra.localhost",
56+
"jwks_uri": "http://hydra.localhost/.well-known/jwks.json",
57+
"registration_endpoint": "http://client-register/registration",
58+
"request_object_signing_alg_values_supported": [
59+
"none",
60+
"RS256",
61+
"ES256"
62+
],
63+
"request_parameter_supported": true,
64+
"request_uri_parameter_supported": true,
65+
"require_request_uri_registration": true,
66+
"response_modes_supported": [
67+
"query",
68+
"fragment",
69+
"form_post"
70+
],
71+
"response_types_supported": [
72+
"code",
73+
"code id_token",
74+
"id_token",
75+
"token id_token",
76+
"token",
77+
"token id_token code"
78+
],
79+
"revocation_endpoint": "http://hydra.localhost/oauth2/revoke",
80+
"scopes_supported": [
81+
"offline_access",
82+
"offline",
83+
"openid"
84+
],
85+
"subject_types_supported": [
86+
"pairwise",
87+
"public"
88+
],
89+
"token_endpoint": "http://hydra.localhost/oauth2/token",
90+
"token_endpoint_auth_methods_supported": [
91+
"client_secret_post",
92+
"client_secret_basic",
93+
"private_key_jwt",
94+
"none"
95+
],
96+
"userinfo_endpoint": "/userinfo",
97+
"userinfo_signed_response_alg": [
98+
"RS256"
99+
],
100+
"userinfo_signing_alg_values_supported": [
101+
"none",
102+
"RS256"
103+
]
104+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
"authorization_endpoint": "http://hydra.localhost/oauth2/auth",
3+
"backchannel_logout_session_supported": true,
4+
"backchannel_logout_supported": true,
5+
"claims_parameter_supported": false,
6+
"claims_supported": [
7+
"sub"
8+
],
9+
"code_challenge_methods_supported": [
10+
"plain",
11+
"S256"
12+
],
13+
"credentials_endpoint_draft_00": "http://hydra.localhost/credentials",
14+
"credentials_supported_draft_00": [
15+
{
16+
"cryptographic_binding_methods_supported": [
17+
"jwk"
18+
],
19+
"cryptographic_suites_supported": [
20+
"PS256",
21+
"RS256",
22+
"ES256",
23+
"PS384",
24+
"RS384",
25+
"ES384",
26+
"PS512",
27+
"RS512",
28+
"ES512",
29+
"EdDSA"
30+
],
31+
"format": "jwt_vc_json",
32+
"types": [
33+
"VerifiableCredential",
34+
"UserInfoCredential"
35+
]
36+
}
37+
],
38+
"device_authorization_endpoint": "http://hydra.localhost/oauth2/device/auth",
39+
"end_session_endpoint": "http://hydra.localhost/oauth2/sessions/logout",
40+
"frontchannel_logout_session_supported": true,
41+
"frontchannel_logout_supported": true,
42+
"grant_types_supported": [
43+
"authorization_code",
44+
"implicit",
45+
"client_credentials",
46+
"refresh_token",
47+
"urn:ietf:params:oauth:grant-type:device_code"
48+
],
49+
"id_token_signed_response_alg": [
50+
"RS256"
51+
],
52+
"id_token_signing_alg_values_supported": [
53+
"RS256"
54+
],
55+
"issuer": "http://hydra.localhost",
56+
"jwks_uri": "http://hydra.localhost/.well-known/jwks.json",
57+
"registration_endpoint": "http://client-register/registration",
58+
"request_object_signing_alg_values_supported": [
59+
"none",
60+
"RS256",
61+
"ES256"
62+
],
63+
"request_parameter_supported": true,
64+
"request_uri_parameter_supported": true,
65+
"require_request_uri_registration": true,
66+
"response_modes_supported": [
67+
"query",
68+
"fragment",
69+
"form_post"
70+
],
71+
"response_types_supported": [
72+
"code",
73+
"code id_token",
74+
"id_token",
75+
"token id_token",
76+
"token",
77+
"token id_token code"
78+
],
79+
"revocation_endpoint": "http://hydra.localhost/oauth2/revoke",
80+
"scopes_supported": [
81+
"offline_access",
82+
"offline",
83+
"openid"
84+
],
85+
"subject_types_supported": [
86+
"pairwise",
87+
"public"
88+
],
89+
"token_endpoint": "http://hydra.localhost/oauth2/token",
90+
"token_endpoint_auth_methods_supported": [
91+
"client_secret_post",
92+
"client_secret_basic",
93+
"private_key_jwt",
94+
"none"
95+
],
96+
"userinfo_endpoint": "/userinfo",
97+
"userinfo_signed_response_alg": [
98+
"RS256"
99+
],
100+
"userinfo_signing_alg_values_supported": [
101+
"none",
102+
"RS256"
103+
]
104+
}

oauth2/handler.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ const (
5858
AuthPath = "/oauth2/auth"
5959
LogoutPath = "/oauth2/sessions/logout"
6060

61-
VerifiableCredentialsPath = "/credentials"
62-
UserinfoPath = "/userinfo"
63-
WellKnownPath = "/.well-known/openid-configuration"
64-
JWKPath = "/.well-known/jwks.json"
61+
VerifiableCredentialsPath = "/credentials"
62+
UserinfoPath = "/userinfo"
63+
WellKnownPath = "/.well-known/openid-configuration"
64+
OauthAuthorizationServerPath = "/.well-known/oauth-authorization-server"
65+
JWKPath = "/.well-known/jwks.json"
6566

6667
// IntrospectPath points to the OAuth2 introspection endpoint.
6768
IntrospectPath = "/oauth2/introspect"
@@ -125,6 +126,8 @@ func (h *Handler) SetRoutes(admin *httprouterx.RouterAdmin, public *httprouterx.
125126
public.Handler("POST", RevocationPath, corsMiddleware(http.HandlerFunc(h.revokeOAuth2Token)))
126127
public.Handler("OPTIONS", WellKnownPath, corsMiddleware(http.HandlerFunc(h.handleOptions)))
127128
public.Handler("GET", WellKnownPath, corsMiddleware(http.HandlerFunc(h.discoverOidcConfiguration)))
129+
public.Handler("OPTIONS", OauthAuthorizationServerPath, corsMiddleware(http.HandlerFunc(h.handleOptions)))
130+
public.Handler("GET", OauthAuthorizationServerPath, corsMiddleware(http.HandlerFunc(h.discoverOidcConfiguration)))
128131
public.Handler("OPTIONS", UserinfoPath, corsMiddleware(http.HandlerFunc(h.handleOptions)))
129132
public.Handler("GET", UserinfoPath, corsMiddleware(http.HandlerFunc(h.getOidcUserInfo)))
130133
public.Handler("POST", UserinfoPath, corsMiddleware(http.HandlerFunc(h.getOidcUserInfo)))

oauth2/handler_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,3 +369,35 @@ func TestHandlerWellKnown(t *testing.T) {
369369
snapshotx.SnapshotT(t, wellKnownResp)
370370
})
371371
}
372+
373+
func TestHandlerOauthAuthorizationServer(t *testing.T) {
374+
ctx := context.Background()
375+
conf := testhelpers.NewConfigurationWithDefaults()
376+
t.Run(fmt.Sprintf("hsm_enabled=%v", conf.HSMEnabled()), func(t *testing.T) {
377+
conf.MustSet(ctx, config.KeyScopeStrategy, "DEPRECATED_HIERARCHICAL_SCOPE_STRATEGY")
378+
conf.MustSet(ctx, config.KeyIssuerURL, "http://hydra.localhost")
379+
conf.MustSet(ctx, config.KeySubjectTypesSupported, []string{"pairwise", "public"})
380+
conf.MustSet(ctx, config.KeyOIDCDiscoverySupportedClaims, []string{"sub"})
381+
conf.MustSet(ctx, config.KeyOAuth2ClientRegistrationURL, "http://client-register/registration")
382+
conf.MustSet(ctx, config.KeyOIDCDiscoveryUserinfoEndpoint, "/userinfo")
383+
reg := testhelpers.NewRegistryMemory(t, conf, &contextx.Default{})
384+
385+
h := oauth2.NewHandler(reg, conf)
386+
387+
r := x.NewRouterAdmin(conf.AdminURL)
388+
h.SetRoutes(r, &httprouterx.RouterPublic{Router: r.Router}, func(h http.Handler) http.Handler {
389+
return h
390+
})
391+
ts := httptest.NewServer(r)
392+
defer ts.Close()
393+
394+
res, err := http.Get(ts.URL + "/.well-known/oauth-authorization-server")
395+
require.NoError(t, err)
396+
defer res.Body.Close()
397+
398+
var wellKnownResp hydra.OidcConfiguration
399+
err = json.NewDecoder(res.Body).Decode(&wellKnownResp)
400+
require.NoError(t, err, "problem decoding wellknown json response: %+v", err)
401+
snapshotx.SnapshotT(t, wellKnownResp)
402+
})
403+
}

0 commit comments

Comments
 (0)