-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adjust the primer towards OIDC Federation #208
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -98,7 +98,7 @@ Several actors are at play in our example Solid-OIDC authentication flows: | |
<dd>Decent Photos is a Solid compliant application and has a URI of its own, | ||
which resolves to a Client ID Document. An RP's Client ID Document | ||
contains information identifying them as a registered OAuth 2.0 client | ||
application. Decent Photo's URI is `https://decentphotos.example/client_id`</dd> | ||
application. Decent Photo's URI is `https://decentphotos.example`</dd> | ||
<dt id="bob-pod">Bob's Storage</dt> | ||
<dd>We will be trying to access photos stored in Bob's Storage. In our example, Bob | ||
is a friend of Alice and has previously indicated via access control that Alice | ||
|
@@ -235,6 +235,8 @@ Response Body: | |
} | ||
``` | ||
|
||
Issue: OIDC Federation defines `client_registration_types_supported`, should it be addedhere, to `.well-known/oidc-federation` or both? | ||
|
||
The thing we care about here is the `authorization_endpoint` field. This will | ||
be the url we use when we're ready to send an authorization request to the OP. | ||
|
||
|
@@ -269,11 +271,13 @@ challenge anywhere. | |
Now that the web app is registered, we can finally make an auth request to authorize the web | ||
application. | ||
|
||
Issue: Change to match [OIDC Federation - Authentication Request](https://openid.net/specs/openid-connect-federation-1_0.html#name-authentication-request) | ||
|
||
```http | ||
GET https://secureauth.example/authorize?response_type=code& | ||
redirect_uri=https%3A%2F%2Fdecentphotos.example%2Fcallback& | ||
scope=openid%20webid%20offline_access& | ||
client_id=https%3A%2F%2Fdecentphotos.example%client_id& | ||
client_id=https%3A%2F%2Fdecentphotos.example& | ||
code_challenge_method=S256& | ||
code_challenge=HSi9dwlvRpNHCDm-L8GOdM16qcb0tLHPZqQSvaWXTI0 | ||
``` | ||
|
@@ -289,53 +293,84 @@ That URL might look a little complex, but it's essentially a request to | |
- `openid` is a scope that is needed to verify Alice's identity. | ||
- `webid` is required by the Solid-OIDC specification to denote a WebID login. | ||
- `offline_access`: Is required to get a refresh token. | ||
- `client_id=https%3A%2F%2Fdecentphotos.example%2Fclient_id`: Usually the client id of a Solid | ||
application is the app's URI (in our case `https://decentphotos.example/client_id`) as seen here. | ||
- `client_id=https%3A%2F%2Fdecentphotos.example`: Usually the client id of a Solid | ||
application is the app's URI (in our case `https://decentphotos.example`) as seen here. | ||
- `code_challenge_method=S256`: Tells the OP that our code challenge was transformed using SHA-256. | ||
- `code_challenge=HSi9dwlvRpNHCDm-L8GOdM16qcb0tLHPZqQSvaWXTI0`: The [=code challenge=] we generated before. | ||
|
||
Note: If the app doesn't have a URI, you can either register an app using static registration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to keep mentioning static registration? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For an OP that is not part of a federation, how would a client know that the OP supports There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure how that is related to (not) mentioning static registration? Did you mean to respons to the other conversation on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To answer to your question: I was assuming that a Solid-OIDC compliant OP would always adhere to the OpenID Federation spec, regardless of it being part of an actual federation or not; so every OP would always have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aside: @woutermont this is in a different thread because the GH interface, for some inexplicable reason, will not allow me to comment on the relevant thread. One perspective is that, if a Solid-OIDC OP is going to support the processing of RP Federation trust chains, it would make sense to also require the OP to participate in a Federation. After all, the OP is already implementing most of OIDC Federation, it could sure support the remaining APIs easily enough. The other perspective is that the specific need on the part of Solid-OIDC is to be able to uniquely and securely identify RPs. Adding requirements to OPs above and beyond the needs of Solid only adds a burden to implementers. I suspect that many Solid-OIDC OP implementations will also participate in a Federation, but I am wary of adding requirements that are not strictly necessary. It will be important to ensure that there is nothing in the text of the specification that prevents an IdP implementer from adding full OP support for federation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I totally agree, @acoburn! We should not make it any more difficult for OPs than necessary. I just don't see how my suggestion (not including Unless I am mistaken, this entails no other requirements from the OP. |
||
via some UI on the OP or use [dynamic registration](https://openid.net/specs/openid-connect-registration-1_0.html). | ||
|
||
<h4 id="authorization-code-pkce-flow-step-7" class="no-num">7. Fetch RP Client ID Document</h4> | ||
<h4 id="authorization-code-pkce-flow-step-7" class="no-num">7. Fetch RP Metadata</h4> | ||
|
||
If an app URI is provided as the client id (see note above to see other options), we must | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd expect a break or header here to indicate that we're now switching from the app perspective to the OP perspective. Strange I haven't missed that before. |
||
fetch that app URI to confirm its validity. | ||
[Obtaining Federation Entity Configuration Information](https://openid.net/specs/openid-connect-federation-1_0.html#name-obtaining-federation-entity) | ||
|
||
For the URI `https://decentphotos.example/client_id`, request the Client ID Document with: | ||
For the URI `https://decentphotos.example`, request the Entity Statement from: | ||
```http | ||
GET https://decentphotos.example/webid | ||
GET https://decentphotos.example/.well-known/openid-federation | ||
``` | ||
|
||
Response: | ||
```jsonld | ||
|
||
```json | ||
{ | ||
"@context": [ "https://www.w3.org/ns/solid/oidc-context.jsonld" ], | ||
|
||
"client_id": "https://decentphtos.example/client_id", | ||
"client_name": "DecentPhotos", | ||
"redirect_uris": [ "https://decentphotos.example/callback" ], | ||
"post_logout_redirect_uris": [ "https://decentphotos.example/logout" ], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Post-logout redirect URI disappeared? |
||
"client_uri": "https://decentphotos.example/", | ||
"logo_uri": "https://decentphotos.example/logo.png", | ||
"tos_uri": "https://decentphotos.example/tos.html", | ||
"scope": "openid webid offline_access", | ||
"grant_types": [ "refresh_token", "authorization_code" ], | ||
"response_types": [ "code" ], | ||
"default_max_age": 3600, | ||
"require_auth_time": true | ||
} | ||
"iss": "https://decentphotos.example", | ||
"sub": "https://decentphotos.example", | ||
"iat": 1516239022, | ||
"exp": 1516298022, | ||
"metadata": { | ||
"openid_relying_party": { | ||
"application_type": "web", | ||
"redirect_uris": [ | ||
"https://decentphotos.example/callback" | ||
], | ||
"organization_name": "DecentOrg", | ||
"client_id": "https://decentphotos.example", | ||
"client_name": "DecentPhotos", | ||
"client_uri": "https://decentphotos.example", | ||
"logo_uri": "https://decentphotos.example/logo.png", | ||
"tos_uri": "https://decentphotos.example/tos.html", | ||
"scope": "openid webid offline_access", | ||
"grant_types": [ | ||
"authorization_code", | ||
"refresh_token" | ||
], | ||
"response_types": [ "code" ], | ||
"default_max_age": 3600, | ||
"require_auth_time": true | ||
"signed_jwks_uri": "https://openid.sunet.se/rp/jwks.jose", | ||
"jwks_uri":"https://openid.sunet.se/rp/signed_jwks.json" | ||
} | ||
}, | ||
"jwks": { | ||
"keys": [ | ||
{ | ||
"alg": "RS256", | ||
"e": "AQAB", | ||
"key_ops": [ | ||
"verify" | ||
], | ||
"kid": "key1", | ||
"kty": "RSA", | ||
"n": "pnXBOusEANuug6ewezb9J_...", | ||
"use": "sig" | ||
} | ||
] | ||
}, | ||
"authority_hints": [ | ||
"https://decent.example/federation" | ||
] | ||
} | ||
``` | ||
|
||
Notice that the application Client ID Document contains a JSON-LD representation of an | ||
[OIDC Client Registration](https://tools.ietf.org/html/rfc7591#section-2). | ||
It also must use the specific <code>"@context": ["https://www.w3.org/ns/solid/oidc-context.jsonld"]</code>. | ||
Issue: Details from [OIDC Federation - Processing the Authentication Request](https://openid.net/specs/openid-connect-federation-1_0.html#name-processing-the-authenticati) | ||
|
||
<h4 id="authorization-code-pkce-flow-step-8" class="no-num">8. Validate redirect url with Client ID Document</h4> | ||
<h4 id="authorization-code-pkce-flow-step-8" class="no-num">8. Validate redirect url with RP Metadata</h4> | ||
|
||
Check to be sure that the `redirect_uri` value provided in the auth request | ||
(`https://decentphotos.example/callback`) is listed in the `redirect_uris` array in the | ||
Client ID Document. If it is not, the OP must reject the request. In our case, the | ||
RP Metadata. If it is not, the OP must reject the request. In our case, the | ||
`redirect_uri` is valid, so we may continue. | ||
|
||
<h4 id="authorization-code-pkce-flow-step-9" class="no-num">9. Alice Logs In</h4> | ||
|
@@ -354,7 +389,7 @@ id, the [=code challenge=], the user's webid, their desired response types, and | |
```json | ||
{ | ||
"m-OrTPHdRsm8W_e9P0J2Bt": { | ||
"client_id": "https://decentphotos.example/client_id", | ||
"client_id": "https://decentphotos.example", | ||
"code_challenge": "HSi9dwlvRpNHCDm-L8GOdM16qcb0tLHPZqQSvaWXTI0", | ||
"webid": "https://alice.coolpod.example/profile/card#me", | ||
"response_types": [ "code" ], | ||
|
@@ -479,7 +514,7 @@ Body: | |
code_verifier=JXPOuToEB7& | ||
code=m-OrTPHdRsm8W_e9P0J2Bt& | ||
redirect_uri=https%3A%2F%2Fdecentphotos.example%2Fcallback& | ||
client_id=https%3A%2F%2Fdecentphotos.example%2Fclient_id | ||
client_id=https%3A%2F%2Fdecentphotos.example | ||
``` | ||
|
||
- `headers.DPoP: "eyJhbGciOiJFUz..."`: The DPoP token we generated before. This will tell the | ||
|
@@ -494,7 +529,7 @@ Body: | |
- `body.code=m-OrTPHdRsm8W_e9P0J2Bt`: The [=authorization code=] that we received from the OP upon redirect | ||
- `body.redirect_uri`: The app's redirect url. In this case, this isn't needed because we're | ||
doing an AJAX request. | ||
- `body.client_id=https%3A%2F%2Fdecentphotos.example%client_id`: The app's client id. | ||
- `body.client_id=https%3A%2F%2Fdecentphotos.example`: The app's client id. | ||
|
||
Once this request is completed decentphotos can remove the code verifier from session storage. | ||
|
||
|
@@ -559,8 +594,8 @@ Token Body: | |
```json | ||
{ | ||
"sub": "https://alice.coolpod.example/profile/card#me", | ||
"aud": [ "solid", "https://decentphotos.example/client_id"], | ||
"azp": "https://decentphotos.example/client_id" | ||
"aud": [ "solid", "https://decentphotos.example"], | ||
"azp": "https://decentphotos.example" | ||
"webid": "https://alice.coolpod.example/profile/card#me", | ||
"iss": "https://secureauth.example", | ||
"jti": "844a095c-9cdb-47e5-9510-1dba987c0a5f", | ||
|
@@ -574,10 +609,10 @@ Token Body: | |
|
||
- `"sub": "https://alice.coolpod.example/profile/card#me"`: The subject claim. It must | ||
be the same as the authenticated user's WebID. | ||
- `"aud": "https://decentphotos.example/client_id"`: The token's audience. Because an | ||
- `"aud": "https://decentphotos.example"`: The token's audience. Because an | ||
id token is intended for the client and any Solid Authorization Server, | ||
its audience is the client id and the string "solid". | ||
- `"azp": "https://decentphotos.example/client_id"`: The token's authorized party. Because an | ||
- `"azp": "https://decentphotos.example"`: The token's authorized party. Because an | ||
id_token is intended to be used by the client, its authorized party is the client id. | ||
- `"webid": "https://alice.coolpod.example/profile/card#me"`: The WebID of the user that | ||
logged in | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should definitely be added to OpenID Metadata resource (
/.well-known/openid-configuration
) for OPs that support clients from a federation.If the OpenID Provider participates in a federation, the OP federation metadata would also contain this information (note the resource path:
.well-known/openid-federation
).As I have been considering this change, I have been imagining the relying parties participating in an OIDC federation, but that it would entirely optional for an OpenID Provider to participate in a federation. Or are you thinking that this would be a requirement for Solid OIDC Providers as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I'm going to add it to
/.well-known/openid-configuration
.I think we should start with the minimum required, probably enough for RPs to act as entities in federation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first I agreed, but now I'm fairly certain that the Federation spec only means to add that to the
.well-known/openid-federation
config, not change anything about the OIDC configuration. As long as we're not talking about OPs from a federation perspective, I thus think it should not be added anywhere.