crspybits / SolidAuthSwift

Swift-based authentication for a Solid Pod
MIT License
7 stars 1 forks source link

Trying to use issuer: https://broker.pod.inrupt.com: 400 response #3

Closed crspybits closed 3 years ago

crspybits commented 3 years ago

I'm not getting as far in my code as using my webid I think, but my webid is: https://pod.inrupt.com/crspybits/profile/card#me

When I attempt to do the registration step, I get a response:

2021-09-05 16:10:15.496195-0600 SolidAuthSwiftDemo[46870:8846738] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed
2021-09-05T16:10:16-0600 debug  : Received data: Optional("{\"authorization_endpoint\":\"https://broker.pod.inrupt.com/authorization\",\"claims_supported\":[\"sub\",\"webid\",\"iss\",\"aud\"],\"code_challenge_methods_supported\":[\"plain\",\"S256\"],\"dpop_signing_alg_values_supported\":[\"RS256\",\"ES256\"],\"end_session_endpoint\":\"https://broker.pod.inrupt.com/endsession\",\"grant_types_supported\":[\"authorization_code\",\"refresh_token\",\"client_credentials\"],\"id_token_signing_alg_values_supported\":[\"RS256\",\"ES256\"],\"issuer\":\"https://broker.pod.inrupt.com/\",\"jwks_uri\":\"https://broker.pod.inrupt.com/jwks\",\"registration_endpoint\":\"https://broker.pod.inrupt.com/registration\",\"response_types_supported\":[\"code\"],\"revocation_endpoint\":\"https://broker.pod.inrupt.com/revoke\",\"scopes_supported\":[\"openid\",\"offline_access\",\"profile\"],\"solid_oidc_supported\":\"https://solidproject.org/TR/solid-oidc\",\"subject_types_supported\":[\"public\"],\"token_endpoint\":\"https://broker.pod.inrupt.com/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\"],\"userinfo_endpoint\":\"https://broker.pod.inrupt.com/userinfo\"}")
2021-09-05T16:10:16-0600 debug  : Received url response: <NSHTTPURLResponse: 0x600003015760> { URL: https://broker.pod.inrupt.com/.well-known/openid-configuration } { Status Code: 200, Headers {
    "Content-Length" =     (
        1048
    );
    "Content-Type" =     (
        "application/json"
    );
    Date =     (
        "Sun, 05 Sep 2021 22:10:16 GMT"
    );
    "Strict-Transport-Security" =     (
        "max-age=15724800; includeSubDomains"
    );
} }
2021-09-05T16:10:16-0600 debug  : JSONString: dict: [AnyHashable("client_name"): "Neebla", AnyHashable("response_types"): "code id_token", AnyHashable("application_type"): "native", AnyHashable("grant_types"): ["authorization_code"], AnyHashable("token_endpoint_auth_method"): "client_secret_post", AnyHashable("redirect_uris"): ["biz.SpasticMuffin.Neebla.demo:/mypath"]]
2021-09-05T16:10:16-0600 debug  : postBody: 231 bytes
2021-09-05T16:10:16-0600 debug  : Headers: Optional(["Content-Type": "application/json"])
2021-09-05T16:10:16-0600 debug  : URL Request: https://broker.pod.inrupt.com/registration
2021-09-05T16:10:16-0600 error  : Failed client registration: oAuthError("Optional([\"error\": invalid_request, \"error_description\": 400 Bad Request])")
2021-09-05T16:10:16-0600 error  : Sign In Controller failed: oAuthError("Optional([\"error\": invalid_request, \"error_description\": 400 Bad Request])")
crspybits commented 3 years ago

Asked question here: https://forum.solidproject.org/t/trying-to-go-through-authorization-flow-with-https-pod-inrupt-com-crspybits-profile-card-me/4642

crspybits commented 3 years ago

@wrmack -- any ideas on this?

NSeydoux commented 3 years ago

@crspybits, I'll double check with the broker's developers, but I'm not 100% sure it supports client secret post yet. Have you tried basic auth ?

In any case, if you check the broker configuration, you'll see that the only supported response type is code. Including id_token there suggests you want to use a hybrid flow, which isn't supported. You'll get an ID token back from the token endpoint if your grant request includes the scope openid.

crspybits commented 3 years ago

Thanks!! This helps. I'd been operating pretty much in the dark about response_types_supported. Looks like I need to pay attention to that or figure out a minimal support path. I'm going to put this link here for my reference later.

I'm not quite sure what you mean by client secret post-- is that referring to dynamic registration?

As for basic auth, I assume you mean this? I haven't tried that. Is that part of the Solid authentication standard?

wrmack commented 3 years ago

I thought I replied to your query some time ago but can't see my reply. I must have forgotten to the Comment button.

I experimented with my Get Tokens app and the following works in MacOS and iOS. I get the tokens and can then access the user info end-point. I read somewhere that for native apps it is best not to use a client secret. A client secret is not really necessary anyway with the PKCE and DPOP mechanisms. Hope this helps.


Stage 1: Discovery

The app requests the provider's configuration endpoint .well-known/openid-configuration to get information for subsequent requests.

The response is JSON data.

Those providers who conform to the Solid-OIDC protocol will include in the response: "solid_oidc_supported": "https://solidproject.org/TR/solid-oidc"


The request is to: https://broker.pod.inrupt.com/.well-known/openid-configuration

The response is:

{ "solid_oidc_supported" : "https://solidproject.org/TR/solid-oidc", "dpop_signing_alg_values_supported" : [ "RS256", "ES256" ], "grant_types_supported" : [ "authorization_code", "refresh_token", "client_credentials" ], "jwks_uri" : "https://broker.pod.inrupt.com/jwks", "registration_endpoint" : "https://broker.pod.inrupt.com/registration", "code_challenge_methods_supported" : [ "plain", "S256" ], "end_session_endpoint" : "https://broker.pod.inrupt.com/endsession", "scopes_supported" : [ "openid", "offline_access", "profile" ], "subject_types_supported" : [ "public" ], "token_endpoint" : "https://broker.pod.inrupt.com/token", "issuer" : "https://broker.pod.inrupt.com/", "revocation_endpoint" : "https://broker.pod.inrupt.com/revoke", "claims_supported" : [ "sub", "webid", "iss", "aud" ], "id_token_signing_alg_values_supported" : [ "RS256", "ES256" ], "token_endpoint_auth_methods_supported" : [ "client_secret_basic", "client_secret_post" ], "userinfo_endpoint" : "https://broker.pod.inrupt.com/userinfo", "response_types_supported" : [ "code" ], "authorization_endpoint" : "https://broker.pod.inrupt.com/authorization" }


Stage 2: Dynamic registration

The client app ("Get tokens") is not already registered with the OpenID Provider. We register the client using OpenID's dynamic registration protocol. A POST request is made using JSON data.

The OpenID Provider responds with a client id.


The request is to: https://broker.pod.inrupt.com/registration http method: POST http headers: ["Content-Type": "application/json"] http body: { "application_type" : "native", "grant_types" : [ "authorization_code" ], "token_endpoint_auth_method" : "none", "redirect_uris" : [ "com.wm.get-tokens:/mypath" ], "client_name" : "Get tokens", "response_types" : [ "code" ] }

The response is:

{ "application_type" : "native", "grant_types" : [ "authorization_code" ], "redirect_uris" : [ "com.wm.get-tokens:/mypath" ], "response_types" : [ "code" ], "contacts" : [

], "token_endpoint_auth_method" : "none", "id_token_signed_response_alg" : "ES256", "client_id" : "4hR0ugOYPccHUxjzFSdXh1um30Mx0yjb", "client_name" : "Get tokens" }


Stage 3: Get authorization code

A GET request with query. The OpenID Provider provides a login page. After successful login, the provider redirects to the redirect url with a query string appended to the url containing an authorization code.

The app will use the authorization code to request tokens.


The request is to: https://broker.pod.inrupt.com/authorization?code_challenge=jIGbxn0g5WCOQEi4afl5Ef362fITJ6P15YTEtU07XOs&response_type=code&redirect_uri=com.wm.get-tokens:/mypath&code_challenge_method=S256&state=9X-Z2IGjkcO7M2po9P1zVIMntZESFhC-U4uEIcVm6mA&scope=openid%20profile%20offline_access&client_id=4hR0ugOYPccHUxjzFSdXh1um30Mx0yjb

Summary - the request's query components:

NSeydoux commented 3 years ago

The different steps described by @wrmack describe well what the expected flow should be. It maps to a sequence diagram we have in our documentation (in OIDC, client means the application): Auth code flow sequence diagram

I'm not quite sure what you mean by client secret post-- is that referring to dynamic registration?

As for basic auth, I assume you mean this? I haven't tried that. Is that part of the Solid authentication standard?

Here's a short explanation: the client (the app) needs to be registered to the Solid Identity Provider before redirecting the user to the authorization endpoint. "Being registered" means having at least a client ID, and optionally a client secret. These identifiers are provided to the Solid Identity Provider in particular when redirecting the client to the authorization endpoint (see "Stage 3" of @wrmack response), and when sending a request to the token endpoint. In the latter case, several ways of sending the identifiers are defined in the OIDC spec, among which are:

A Solid Identity Provider may support only one of these, or it may support many. That's why a specific client may want to make explicit how it will identify itself using the token_endpoint_auth_method client metadata during registration. In your case, you're using client_secret_post (or at least that's what the logs you shared show), and maybe you could consider using client_secret_basic. Both seem to be supported by https://broker.pod.inrupt.com, but I'll check if that's really the case.

wrmack commented 3 years ago

Re native apps and authentication method see section 8.5 here: https://datatracker.ietf.org/doc/html/rfc8252#section-8.5. Having a client secret is not too much of a problem if dynamic registration is used because the secret is generated each time, but the general advice is that native apps should not use secrets at all. If dynamic registration is not used then, for example with OAuth with Google, a client secret would need to be stored with the app and included in every app downloaded from the App Store.

crspybits commented 3 years ago

Thank so much Gentlemen!! This gives me quite a bit of grist for my mill to push my efforts along. I'll dig into this further this weekend, when the day job doesn't interfere ;).

@wrmack On the topic of

general advice is that native apps should not use secrets at all

I have a further concern about the use of Solid resource requests, after authentication. The concern is about private/public keys, and I bring it up in https://github.com/crspybits/SolidAuthSwift/issues/2. This is not an immediate concern for me, but I I'm thinking about others who might use https://github.com/crspybits/SolidAuthSwift/ for native iOS app development without their own custom server.

crspybits commented 3 years ago

Well, the immediate problem was that I was not giving an array in the registration:

"response_types" : [
"code"
]

Once I change that, I get to the sign in screen with the redirect.

crspybits commented 3 years ago

Well, I'm getting a step further. I can sign in successfully:

2021-09-10T18:57:15-0600 debug : requestURL: https://broker.pod.inrupt.com/authorization?scope=openid%20offline_access%20profile%20webid&nonce=B6a76gZkna1cIQB5GqqEstzk2KxHxwDaBkRaNlqJl-o&code_challenge_method=S256&code_challenge=NX6JifCACO-vHzn5u41hLhv-FZjb10onpoHQoPfu6Qo&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&state=TgtSRPa6VwLMfp0iMvdyhLj6D65RdWoJxquXn1EFNDo&client_id=bmozAcZ7alSFw5XongrP8GXSyXRjZodj&response_type=code%20id_token 2021-09-10T18:57:53-0600 debug : presentAuthenticationViewController: Optional(biz.spasticmuffin.neebla.demo:/mypath?code=QXApcurnKfNpbDdb56WqionJinwKRUq6&state=TgtSRPa6VwLMfp0iMvdyhLj6D65RdWoJxquXn1EFNDo); nil 2021-09-10T18:57:53-0600 debug : Sign In Controller succeeded : Response(authResponse: <SolidAuthSwiftUI.AuthorizationResponse: 0x6000034ec680>, parameters: SolidAuthSwiftTools.CodeParameters(tokenEndpoint: https://broker.pod.inrupt.com/token, jwksURL: https://broker.pod.inrupt.com/jwks, codeVerifier: "c3QGBJ65vdUi1UA0YRqqXZguN7T9FQcbPVPLIDOCor0", code: "QXApcurnKfNpbDdb56WqionJinwKRUq6", redirectUri: "biz.SpasticMuffin.Neebla.demo:/mypath", clientId: "bmozAcZ7alSFw5XongrP8GXSyXRjZodj"), storageIRI: nil) 2021-09-10T18:57:53-0600 debug : Controller response: Response(authResponse: <SolidAuthSwiftUI.AuthorizationResponse: 0x6000034ec680>, parameters: SolidAuthSwiftTools.CodeParameters(tokenEndpoint: https://broker.pod.inrupt.com/token, jwksURL: https://broker.pod.inrupt.com/jwks, codeVerifier: "c3QGBJ65vdUi1UA0YRqqXZguN7T9FQcbPVPLIDOCor0", code: "QXApcurnKfNpbDdb56WqionJinwKRUq6", redirectUri: "biz.SpasticMuffin.Neebla.demo:/mypath", clientId: "bmozAcZ7alSFw5XongrP8GXSyXRjZodj"), storageIRI: nil)

However, the token request POST is failing (i.e., this step https://solid.github.io/solid-oidc/primer/#authorization-code-pkce-flow-step-14):

Body: grant_type=authorization_code&code_verifier=c3QGBJ65vdUi1UA0YRqqXZguN7T9FQcbPVPLIDOCor0&code=QXApcurnKfNpbDdb56WqionJinwKRUq6&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&client_id=bmozAcZ7alSFw5XongrP8GXSyXRjZodj

request: Optional(https://broker.pod.inrupt.com/token)

request.allHTTPHeaderFields: Optional(["DPoP": "eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMjU2IiwiandrIjp7ImtpZCI6ImV4YW1wbGUiLCJ1c2UiOiJzaWciLCJuIjoicXkxS1RGdzVHanRHZ0p1aXV5bFk0UHhmeXM5eGt6VHY5WkJvSkJYT3BRR3JLWGpLcWN4TXgtTEFRMFJWdy1HYnM2LUVtakFUNEVVbk1EN2lwZGxlYW9xcFROTDdUTld0SzRUSmlIbllZNHlrOHRaMG84bHFreGJpOFVOQmdOY3g3N3VTa1d5Rmx2NWZqTll0Q0ZkZ3FnYjlJdlRxOXdJTHZReTU2bGY4TWFfU01OMW1hci1OTlhhRGZtaW9SNm5wX3pKbEFwazBiUlF3SEF0emhGWDlWUXA1YTFnbVdNcE9wVGVYVHF1ck83UDhCM3Ixc2pCYm15R0lBdDdUdzdFRmdEOXk2Q1dOYXBya3RSaDVVUmFVWnVLLVJGNm8ybENnNGs3OWJCUUh2bXJRdE12STh5QlpETm9oUTFSeVlTUHNLY004X1hqLUlTWnNsdVM1c1BaR2ZyWFdqS2sxMkZiMlg2NFZVbjlpVkwtc2RhRHJuamlaUXhZbVNlNEk4YmtIdWJvUW5LVHFrQ3pEZlJjblRrLXp5R0JxakVoN0QzMC1wS054bTQyQTh4TXdrUTlnT0huZmQ5Q3ZWN3FndWVHcFZfbFJQWGU1M1cwbkd6Z1pnQktGNXR1Sms5UWdkd1hxcHRrZXdNVjNwdnp4MGxTTnpBOHY0MnBkUEZNd3JzcEhSNUw1ZEVhenJzTUp1WjhqQUFpeUNOUnNBcFFtZFc1dHUwSndLWDdaa2s2Nlg3cWpPTW8tV1kwOENEMy01TkI5dExRV0FpYnloNHVLMnhoUm9lMFJ3aDF3UWhFQjBXYi1YRTIzOVdwWG5YQTExTFMwSGJBMVhzLVhmQjNROHYtWWVCNDNFY0E4TDdHbU1yejlCWGhyUks2UXpkSFZodHNMM3FjU3pQUlo2UjAiLCJlIjoiQVFBQiIsImt0eSI6IlJTQSIsImFsZyI6IlJTMjU2In19.eyJqdGkiOiI1QjhFNkQ4RC1CNTY2LTQxNTgtODEyNS0yODdFNEJFMEEwMTQiLCJodHUiOiJodHRwczpcL1wvYnJva2VyLnBvZC5pbnJ1cHQuY29tXC90b2tlbiIsImlhdCI6MTYzMTMyMTkyMC4xNDc2NzMxLCJodG0iOiJQT1NUIn0.oFqC9WXAqu4eBd4RDJ5yvUpWSjQpepscpOzweTjWvad3kvqUB940LAXfDc3EPXwoYJAlpVEWoRmFSdGTt7vSFbulJdClyqnH2KiR7A5DhUT9gpLNBc9kVxqHV3_DTI-OEPdySPPafaMayoa79DuIHJyuYviPCH6wqG7ja5l9GSUI5u58rJUqxCsDDwAmsrk4oEC5MzA8FUQZ32qoU4aqEmFupOU3QCXPc5sq9-Xeczha1QgH60lFCHVvVT6RULIpuG-f08KFf1y53lyPvGeqHIdAUWVNk3eMPXacmD2QgH062dUTWQlzOdmxw7nMciBPn7Rxfx30wspJvTGduN-uAhbtT3mDaSsQ-1fWN-rd5QE2pW5oxdPjS-JDpnuVP2FvVSat5kREuBYVrS534XQaSsHlvU6VdP3N72X_vn3e2h9xhEKPKtYNuRuV7c0uoz6obnhQisJdyppOn2kUHWcxX6jhHBZCGqrRZAXPAsGnjUKV6zZ-fVCywQBEei85z98JX4mrlMpf6QS1fxKkm00aFXPv-XLeCZv0DblrwK7bhSyDRibv8x5vaA7WgRAgEExqpvmWMDfCKQrRWQ8Le_Hn-WfCuRYAVMmwoSRyhPEJC9W7HIGXb9vUEptG7pc-p0Jx5zNwc341L1Tg_KzxFwec-FUN9BKR8YrLH904xsIuZSk", "Content-Type": "application/x-www-form-urlencoded"])

String: Optional("{\"error\":\"invalid_client\",\"error_description\":\"Invalid client credentials\"}") 2021-09-10T18:58:40-0600 error : Failed on TokenRequest: badStatusCode(401)

wrmack commented 3 years ago

Couple of thoughts.

In your request to the authorisation endpoint your response_type should just be ‘code’ not ‘code id_token’ (all you are wanting from the authorisation endpoint is an access code - you will make a separate request to the token endpoint for the id_token).

I did not include a nonce. Don’t know if that has any effect.

Can’t see anything incorrect with the request to the token endpoint.

On 11/09/2021, at 12:59 PM, Christopher Prince @.***> wrote:

Well, I'm getting a step further. I can sign in successfully:

2021-09-10T18:57:15-0600 debug : requestURL: https://broker.pod.inrupt.com/authorization?scope=openid%20offline_access%20profile%20webid&nonce=B6a76gZkna1cIQB5GqqEstzk2KxHxwDaBkRaNlqJl-o&code_challenge_method=S256&code_challenge=NX6JifCACO-vHzn5u41hLhv-FZjb10onpoHQoPfu6Qo&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&state=TgtSRPa6VwLMfp0iMvdyhLj6D65RdWoJxquXn1EFNDo&client_id=bmozAcZ7alSFw5XongrP8GXSyXRjZodj&response_type=code%20id_token 2021-09-10T18:57:53-0600 debug : presentAuthenticationViewController: Optional(biz.spasticmuffin.neebla.demo:/mypath?code=QXApcurnKfNpbDdb56WqionJinwKRUq6&state=TgtSRPa6VwLMfp0iMvdyhLj6D65RdWoJxquXn1EFNDo); nil 2021-09-10T18:57:53-0600 debug : Sign In Controller succeeded : Response(authResponse: <SolidAuthSwiftUI.AuthorizationResponse: 0x6000034ec680>, parameters: SolidAuthSwiftTools.CodeParameters(tokenEndpoint: https://broker.pod.inrupt.com/token, jwksURL: https://broker.pod.inrupt.com/jwks, codeVerifier: "c3QGBJ65vdUi1UA0YRqqXZguN7T9FQcbPVPLIDOCor0", code: "QXApcurnKfNpbDdb56WqionJinwKRUq6", redirectUri: "biz.SpasticMuffin.Neebla.demo:/mypath", clientId: "bmozAcZ7alSFw5XongrP8GXSyXRjZodj"), storageIRI: nil) 2021-09-10T18:57:53-0600 debug : Controller response: Response(authResponse: <SolidAuthSwiftUI.AuthorizationResponse: 0x6000034ec680>, parameters: SolidAuthSwiftTools.CodeParameters(tokenEndpoint: https://broker.pod.inrupt.com/token, jwksURL: https://broker.pod.inrupt.com/jwks, codeVerifier: "c3QGBJ65vdUi1UA0YRqqXZguN7T9FQcbPVPLIDOCor0", code: "QXApcurnKfNpbDdb56WqionJinwKRUq6", redirectUri: "biz.SpasticMuffin.Neebla.demo:/mypath", clientId: "bmozAcZ7alSFw5XongrP8GXSyXRjZodj"), storageIRI: nil) However, requesting tokens is failing:

Body: grant_type=authorization_code&code_verifier=c3QGBJ65vdUi1UA0YRqqXZguN7T9FQcbPVPLIDOCor0&code=QXApcurnKfNpbDdb56WqionJinwKRUq6&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&client_id=bmozAcZ7alSFw5XongrP8GXSyXRjZodj request: Optional(https://broker.pod.inrupt.com/token) request.allHTTPHeaderFields: Optional(["DPoP": "eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMjU2IiwiandrIjp7ImtpZCI6ImV4YW1wbGUiLCJ1c2UiOiJzaWciLCJuIjoicXkxS1RGdzVHanRHZ0p1aXV5bFk0UHhmeXM5eGt6VHY5WkJvSkJYT3BRR3JLWGpLcWN4TXgtTEFRMFJWdy1HYnM2LUVtakFUNEVVbk1EN2lwZGxlYW9xcFROTDdUTld0SzRUSmlIbllZNHlrOHRaMG84bHFreGJpOFVOQmdOY3g3N3VTa1d5Rmx2NWZqTll0Q0ZkZ3FnYjlJdlRxOXdJTHZReTU2bGY4TWFfU01OMW1hci1OTlhhRGZtaW9SNm5wX3pKbEFwazBiUlF3SEF0emhGWDlWUXA1YTFnbVdNcE9wVGVYVHF1ck83UDhCM3Ixc2pCYm15R0lBdDdUdzdFRmdEOXk2Q1dOYXBya3RSaDVVUmFVWnVLLVJGNm8ybENnNGs3OWJCUUh2bXJRdE12STh5QlpETm9oUTFSeVlTUHNLY004X1hqLUlTWnNsdVM1c1BaR2ZyWFdqS2sxMkZiMlg2NFZVbjlpVkwtc2RhRHJuamlaUXhZbVNlNEk4YmtIdWJvUW5LVHFrQ3pEZlJjblRrLXp5R0JxakVoN0QzMC1wS054bTQyQTh4TXdrUTlnT0huZmQ5Q3ZWN3FndWVHcFZfbFJQWGU1M1cwbkd6Z1pnQktGNXR1Sms5UWdkd1hxcHRrZXdNVjNwdnp4MGxTTnpBOHY0MnBkUEZNd3JzcEhSNUw1ZEVhenJzTUp1WjhqQUFpeUNOUnNBcFFtZFc1dHUwSndLWDdaa2s2Nlg3cWpPTW8tV1kwOENEMy01TkI5dExRV0FpYnloNHVLMnhoUm9lMFJ3aDF3UWhFQjBXYi1YRTIzOVdwWG5YQTExTFMwSGJBMVhzLVhmQjNROHYtWWVCNDNFY0E4TDdHbU1yejlCWGhyUks2UXpkSFZodHNMM3FjU3pQUlo2UjAiLCJlIjoiQVFBQiIsImt0eSI6IlJTQSIsImFsZyI6IlJTMjU2In19.eyJqdGkiOiI1QjhFNkQ4RC1CNTY2LTQxNTgtODEyNS0yODdFNEJFMEEwMTQiLCJodHUiOiJodHRwczpcL1wvYnJva2VyLnBvZC5pbnJ1cHQuY29tXC90b2tlbiIsImlhdCI6MTYzMTMyMTkyMC4xNDc2NzMxLCJodG0iOiJQT1NUIn0.oFqC9WXAqu4eBd4RDJ5yvUpWSjQpepscpOzweTjWvad3kvqUB940LAXfDc3EPXwoYJAlpVEWoRmFSdGTt7vSFbulJdClyqnH2KiR7A5DhUT9gpLNBc9kVxqHV3_DTI-OEPdySPPafaMayoa79DuIHJyuYviPCH6wqG7ja5l9GSUI5u58rJUqxCsDDwAmsrk4oEC5MzA8FUQZ32qoU4aqEmFupOU3QCXPc5sq9-Xeczha1QgH60lFCHVvVT6RULIpuG-f08KFf1y53lyPvGeqHIdAUWVNk3eMPXacmD2QgH062dUTWQlzOdmxw7nMciBPn7Rxfx30wspJvTGduN-uAhbtT3mDaSsQ-1fWN-rd5QE2pW5oxdPjS-JDpnuVP2FvVSat5kREuBYVrS534XQaSsHlvU6VdP3N72X_vn3e2h9xhEKPKtYNuRuV7c0uoz6obnhQisJdyppOn2kUHWcxX6jhHBZCGqrRZAXPAsGnjUKV6zZ-fVCywQBEei85z98JX4mrlMpf6QS1fxKkm00aFXPv-XLeCZv0DblrwK7bhSyDRibv8x5vaA7WgRAgEExqpvmWMDfCKQrRWQ8Le_Hn-WfCuRYAVMmwoSRyhPEJC9W7HIGXb9vUEptG7pc-p0Jx5zNwc341L1Tg_KzxFwec-FUN9BKR8YrLH904xsIuZSk", "Content-Type": "application/x-www-form-urlencoded"]) String: Optional("{\"error\":\"invalid_client\",\"error_description\":\"Invalid client credentials\"}") 2021-09-10T18:58:40-0600 error : Failed on TokenRequest: badStatusCode(401) — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/crspybits/SolidAuthSwift/issues/3#issuecomment-917308752, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJVC46DFFIATCH7PKYQMI3UBKSW5ANCNFSM5DPHXDYQ.

crspybits commented 3 years ago

I made those changes, and the situation remains the same. See below.

I'm wondering if this problem has to do with token endpoint authentication. I have been using a DPoP, but I'm confused about where client_secret_basic vs client_secret_post ought to be used.

  1. Client Authentication: https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication suggests this is: when using the Token Endpoint

However, https://solid.github.io/solid-oidc/primer/#authorization-code-pkce-flow-step-14 suggests to use a DPoP token. These seem conflicting statements.


Results from the retest for https://github.com/crspybits/SolidAuthSwift/issues/3#issuecomment-917321581

2021-09-10T21:06:40-0600 debug : requestURL: https://broker.pod.inrupt.com/authorization?code_challenge=2u5UP9TSavD2wmY6_vWilTetglKb2sGMjUWWZk0_dIM&state=ZqiDBMU_SxlcapYtoOphBK-5IGROTvvad_whCNAiOzs&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&response_type=code&scope=offline_access%20profile%20webid%20openid&client_id=AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP&code_challenge_method=S256 2021-09-10T21:07:35-0600 debug : presentAuthenticationViewController: Optional(biz.spasticmuffin.neebla.demo:/mypath?code=Y9hhGL5v3tbyEg0FYuUQlkAkzjG11e9S&state=ZqiDBMU_SxlcapYtoOphBK-5IGROTvvad_whCNAiOzs); nil 2021-09-10T21:07:35-0600 debug : Sign In Controller succeeded : Response(authResponse: <SolidAuthSwiftUI.AuthorizationResponse: 0x6000028b7200>, parameters: SolidAuthSwiftTools.CodeParameters(tokenEndpoint: https://broker.pod.inrupt.com/token, jwksURL: https://broker.pod.inrupt.com/jwks, codeVerifier: "WV1CKsCx5LUE0Ltf8xexdjZaD_W7JpkQqQJQGSZ2C8U", code: "Y9hhGL5v3tbyEg0FYuUQlkAkzjG11e9S", redirectUri: "biz.SpasticMuffin.Neebla.demo:/mypath", clientId: "AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP"), storageIRI: nil) 2021-09-10T21:07:35-0600 debug : Controller response: Response(authResponse: <SolidAuthSwiftUI.AuthorizationResponse: 0x6000028b7200>, parameters: SolidAuthSwiftTools.CodeParameters(tokenEndpoint: https://broker.pod.inrupt.com/token, jwksURL: https://broker.pod.inrupt.com/jwks, codeVerifier: "WV1CKsCx5LUE0Ltf8xexdjZaD_W7JpkQqQJQGSZ2C8U", code: "Y9hhGL5v3tbyEg0FYuUQlkAkzjG11e9S", redirectUri: "biz.SpasticMuffin.Neebla.demo:/mypath", clientId: "AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP"), storageIRI: nil) 2021-09-10T21:08:04-0600 debug : CodeParameters: (base64): Optional("eyJjb2RlVmVyaWZpZXIiOiJXVjFDS3NDeDVMVUUwTHRmOHhleGRqWmFEX1c3SnBrUXFRSlFHU1oyQzhVIiwiY29kZSI6Ilk5aGhHTDV2M3RieUVnMEZZdVVRbGtBa3pqRzExZTlTIiwicmVkaXJlY3RVcmkiOiJiaXouU3Bhc3RpY011ZmZpbi5OZWVibGEuZGVtbzpcL215cGF0aCIsImNsaWVudElkIjoiQVczRWdJbXNWWmNROXZaNkU3UkVpSm56Rkx5dVRwVlAiLCJ0b2tlbkVuZHBvaW50IjoiaHR0cHM6XC9cL2Jyb2tlci5wb2QuaW5ydXB0LmNvbVwvdG9rZW4iLCJqd2tzVVJMIjoiaHR0cHM6XC9cL2Jyb2tlci5wb2QuaW5ydXB0LmNvbVwvandrcyJ9") Passed as htu: https://broker.pod.inrupt.com/token Body: grant_type=authorization_code&code_verifier=WV1CKsCx5LUE0Ltf8xexdjZaD_W7JpkQqQJQGSZ2C8U&code=Y9hhGL5v3tbyEg0FYuUQlkAkzjG11e9S&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&client_id=AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP request: Optional(https://broker.pod.inrupt.com/token) request.allHTTPHeaderFields: Optional(["DPoP": "eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMjU2IiwiandrIjp7ImtpZCI6ImV4YW1wbGUiLCJ1c2UiOiJzaWciLCJuIjoicXkxS1RGdzVHanRHZ0p1aXV5bFk0UHhmeXM5eGt6VHY5WkJvSkJYT3BRR3JLWGpLcWN4TXgtTEFRMFJWdy1HYnM2LUVtakFUNEVVbk1EN2lwZGxlYW9xcFROTDdUTld0SzRUSmlIbllZNHlrOHRaMG84bHFreGJpOFVOQmdOY3g3N3VTa1d5Rmx2NWZqTll0Q0ZkZ3FnYjlJdlRxOXdJTHZReTU2bGY4TWFfU01OMW1hci1OTlhhRGZtaW9SNm5wX3pKbEFwazBiUlF3SEF0emhGWDlWUXA1YTFnbVdNcE9wVGVYVHF1ck83UDhCM3Ixc2pCYm15R0lBdDdUdzdFRmdEOXk2Q1dOYXBya3RSaDVVUmFVWnVLLVJGNm8ybENnNGs3OWJCUUh2bXJRdE12STh5QlpETm9oUTFSeVlTUHNLY004X1hqLUlTWnNsdVM1c1BaR2ZyWFdqS2sxMkZiMlg2NFZVbjlpVkwtc2RhRHJuamlaUXhZbVNlNEk4YmtIdWJvUW5LVHFrQ3pEZlJjblRrLXp5R0JxakVoN0QzMC1wS054bTQyQTh4TXdrUTlnT0huZmQ5Q3ZWN3FndWVHcFZfbFJQWGU1M1cwbkd6Z1pnQktGNXR1Sms5UWdkd1hxcHRrZXdNVjNwdnp4MGxTTnpBOHY0MnBkUEZNd3JzcEhSNUw1ZEVhenJzTUp1WjhqQUFpeUNOUnNBcFFtZFc1dHUwSndLWDdaa2s2Nlg3cWpPTW8tV1kwOENEMy01TkI5dExRV0FpYnloNHVLMnhoUm9lMFJ3aDF3UWhFQjBXYi1YRTIzOVdwWG5YQTExTFMwSGJBMVhzLVhmQjNROHYtWWVCNDNFY0E4TDdHbU1yejlCWGhyUks2UXpkSFZodHNMM3FjU3pQUlo2UjAiLCJlIjoiQVFBQiIsImt0eSI6IlJTQSIsImFsZyI6IlJTMjU2In19.eyJqdGkiOiI5Njc1M0JENS1CNjhELTQ0ODYtOTJGRS1BRjc3MkFCMDc3REUiLCJodHUiOiJyZXF1ZXN0VHlwZS5iYXNpY3MudG9rZW5FbmRwb2ludC5hYnNvbHV0ZVN0cmluZyIsImlhdCI6MTYzMTMyOTY4NC4yNjcwMDc4LCJodG0iOiJQT1NUIn0.MgxfhvyqTEEq5vcSM1mygjh1fbBNYRPQ3OWr-KI8CMukXPbuQ_luxiqTjw_HKwqVsgyS2nN8yJKLNYJ0wvz1TdcQUKWTrduSLZA90j46_pS8IOcGHMDMn30TSRxV2Y191LpaEgsQjPYsYd4E-orTHeQ8yUqp8NOfASLJZ2Tx5No9jIIlOPB_ilRCgtULKj-TAw8RH61JrhA3EDEHcgNcqhRvJTBWP4L4sdf8kjGQc50i73qX0cYahRYPepY8RxAd5a4GOQ9UZJcLtTWTUAmrXUGuLq2fg4S6k3YlmkIPQnS9dKL1nPzhzE2p4pJCR9IwZFgcPjZykQEzeWrE-KGXXkEJWMmkAUYt6lx0M7Gns74bcEJmMae1eZLTQ57IoWn0wyNdFdg8Py1OKG4j2wz0J_NqtIGNzLxLCfnRdNNuV4dEDC_MpN4wty4PJYr5ih8qSV5Wwu5rPi05563WVE3N6oOIaG-FCdLjBofX9Xb9idUVo_6HKR57lryWgV1oEYjTmkFJDRbMC3c4_5Uu4Jt4zCYqp29gw46RLhg7tFyd6KPlzMuprQIkpFT7JjKW7TaCO1BMyngACODUr5HLENqyhlrONURqA-rzEYbsgpTfcRM_2bomG0JY53f3aJ2lOdwkE-QgLjgma0CFixKKCCZbbNnROu6sUqjwqcmrzRjuqlo", "Content-Type": "application/x-www-form-urlencoded"]) String: Optional("{\"error\":\"invalid_client\",\"error_description\":\"Invalid client credentials\"}") 2021-09-10T21:08:13-0600 error : Failed on TokenRequest: badStatusCode(401)

wrmack commented 3 years ago

My full flow below. When registering I used "token_endpoint_auth_method" : “none” and only used client_id. I was not sent a client_secret See my comments a couple of days ago.


Stage 1: Discovery

The app requests the provider's configuration endpoint .well-known/openid-configuration to get information for subsequent requests.

The response is JSON data.

Those providers who conform to the Solid-OIDC protocol will include in the response: "solid_oidc_supported": "https://solidproject.org/TR/solid-oidc"


The request is to: https://broker.pod.inrupt.com/.well-known/openid-configuration

The response is:

{ "solid_oidc_supported" : "https://solidproject.org/TR/solid-oidc", "dpop_signing_alg_values_supported" : [ "RS256", "ES256" ], "grant_types_supported" : [ "authorization_code", "refresh_token", "client_credentials" ], "jwks_uri" : "https://broker.pod.inrupt.com/jwks", "registration_endpoint" : "https://broker.pod.inrupt.com/registration", "code_challenge_methods_supported" : [ "plain", "S256" ], "end_session_endpoint" : "https://broker.pod.inrupt.com/endsession", "scopes_supported" : [ "openid", "offline_access", "profile" ], "subject_types_supported" : [ "public" ], "token_endpoint" : "https://broker.pod.inrupt.com/token", "issuer" : "https://broker.pod.inrupt.com/", "revocation_endpoint" : "https://broker.pod.inrupt.com/revoke", "claims_supported" : [ "sub", "webid", "iss", "aud" ], "id_token_signing_alg_values_supported" : [ "RS256", "ES256" ], "token_endpoint_auth_methods_supported" : [ "client_secret_basic", "client_secret_post" ], "userinfo_endpoint" : "https://broker.pod.inrupt.com/userinfo", "response_types_supported" : [ "code" ], "authorization_endpoint" : "https://broker.pod.inrupt.com/authorization" }

Remarks

Includes 'solid_oidc_supported' parameter.


Stage 2: Dynamic registration

The client app ("Get tokens") is not already registered with the OpenID Provider. We register the client using OpenID's dynamic registration protocol. A POST request is made using JSON data.

The OpenID Provider responds with a client id.


The request is to: https://broker.pod.inrupt.com/registration http method: POST http headers: [ "Content-Type": "application/json" ] http body: { "application_type" : "native", "grant_types" : [ "authorization_code" ], "redirect_uris" : [ "com.wm.get-tokens:/mypath" ], "token_endpoint_auth_method" : "none", "client_name" : "Get tokens", "response_types" : [ "code" ] }

The response is:

{ "contacts" : [

], "token_endpoint_auth_method" : "none", "client_name" : "Get tokens", "redirect_uris" : [ "com.wm.get-tokens:/mypath" ], "grant_types" : [ "authorization_code" ], "client_id" : "E0LPMW3yj67qbaXQRqw9jKC7vAU6nnu7", "id_token_signed_response_alg" : "ES256", "response_types" : [ "code" ], "application_type" : "native" }


Stage 3: Get authorization code

A GET request with query. The OpenID Provider provides a login page. After successful login, the provider redirects to the redirect url with a query string appended to the url containing an authorization code.

The app will use the authorization code to request tokens.


The request is to: https://broker.pod.inrupt.com/authorization?state=n2u_pKF_5kRmars4yHUb8j0PeqdKo4Vc9Wyi3IRwiIw&client_id=E0LPMW3yj67qbaXQRqw9jKC7vAU6nnu7&code_challenge=mHqKCizhlahuOgmtzet1k8Neewz8OzQ4jwOOVhHOjeE&scope=openid%20profile%20offline_access&response_type=code&code_challenge_method=S256&redirect_uri=com.wm.get-tokens:/mypath

Summary - the request's query components:

state=n2u_pKF_5kRmars4yHUb8j0PeqdKo4Vc9Wyi3IRwiIw& client_id=E0LPMW3yj67qbaXQRqw9jKC7vAU6nnu7& code_challenge=mHqKCizhlahuOgmtzet1k8Neewz8OzQ4jwOOVhHOjeE& scope=openid profile offline_access& response_type=code& code_challenge_method=S256& redirect_uri=com.wm.get-tokens:/mypath

The response is: com.wm.get-tokens:/mypath?code=F4uyr..[redacted]..&state=n2u_pKF_5kRmars4yHUb8j0PeqdKo4Vc9Wyi3IRwiIw

Summary - response components:

code=F4uyr..[redacted]..& state=n2u_pKF_5kRmars4yHUb8j0PeqdKo4Vc9Wyi3IRwiIw

Remarks

Authorization code redacted to avoid malicious use by an attacker who is able to see this display or a copy.


Stage 4: Get tokens

The app makes a POST request using the authorization code.

The OP returns an access_token, id_token and refresh_token can be used for accessing protected resources.


The request is to: https://broker.pod.inrupt.com/token http method: POST http headers: [ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "DPoP": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImRwb3Arand0IiwiandrIjp7Im4iOiJ0NHZ3TFJQWUM5djVfRUlOOG1PRGlHbkRXSW5ZU1U4ZXdLTkFBSWt3Tm5YVzlnZU1PTkJkZTA2WUZZamhOZHhtT0ozbGdTWDkzaDJRVEV6aVRjTmFHXzBJTXdMVGhWWFRyOUdsUWJORlRBeUhzeksyeFNqS1VIcTY2ckxYcTl3MnkyYzhPeDhyMGcyaWgtWmxpTndyQXFscjU5UGp6bkRrZFRLcjl0YXhERkRERk9hektiNkFBcTV0ZUgxOUZKMEdvM2NmMnBmSHhqdTJ4SDZLODlkWGdXZGhzZ2lnSVNzU1BkWU9uM3RPbGRFSkdkeXp4eVZDSXFIVGc3UWkyZ3gwS1ZzWktta2RIRTBDSnNLazlvaF9Nd1k1UkdkTUNQUmduNHJYYXBFd01lbnBCc19TQW5EVmFYTV9pTlpqYnI3dHAyZklIYlRmZHNiV01vWE51NDBOS1EiLCJrdHkiOiJSU0EiLCJlIjoiQVFBQiJ9fQ.eyJqdGkiOiJsSFhNbVlzUGdwb3hlTUhiIiwiaHR1IjoiaHR0cHM6XC9cL2Jyb2tlci5wb2QuaW5ydXB0LmNvbVwvdG9rZW4iLCJpYXQiOjE2MzEzMjU4MjMsImh0bSI6IlBPU1QifQ.LKuCv8MSJLjYbphVEOfk6FVjagKZ_FlSHUPVO5Hvo9Lf0yrXgk87IgZStdFuIvcOLNG50D7TMb6S70DfDJzkR53gWLJsxjASA2OIzXMTZHjMqUgdOkudxpX2UbfAhpwcCos-e3XdcT5tCOdsylGRxQ4OFsP29dF4ld0174nGixzMHLHqTOY2OZLzcNoYQpCH8vLgIg8gjEPv4v33A02vdFA9hagqJ3-VPPRbHJuw0PJv9w8n4th36SqwUrhUFP6TXLc1cvZfHrwD4lO2udylyY_35i1vKJlEdKBQ6xsL9hqfSZnx7_qDUfh4d9vkKCrWdb1sD4PxzYw0HMtf30afDA" ] http body: redirect_uri=com.wm.get-tokens:/mypath& grant_type=authorization_code& code=F4uyr..[redacted]..& client_id=E0LPMW3yj67qbaXQRqw9jKC7vAU6nnu7& code_verifier=UiMcE39JRx-BQVGstd2J4Jv4NEY1VguhnVZm1t3xP4A

The response is:

{ "token_type" : "DPoP", "expires_in" : 1861, "id_token" : "eyJraWQiOiJmbExOMUZYMGZMMFciLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJ3cm1hY2siLCJhdWQiOiJFMExQTVczeWo2N3FiYVhRUnF3OWpLQzd2QVU2bm51NyIsIndlYmlkIjoiaHR0cHM6Ly9wb2QuaW5ydXB0LmNvbS93cm1hY2svcHJvZmlsZS9jYXJkI21lIiwiaXNzIjoiaHR0cHM6Ly9icm9rZXIucG9kLmlucnVwdC5jb20vIiwiaWF0IjoxNjMxMzI1ODI0LCJleHAiOjE2MzEzMjc2ODUsImp0aSI6IjM2YjlkYjEyLWZhZGQtNDliMC04YzM4LWUxMmYzMDdhNjdiNSJ9.Qq70r_mqOjE9yZ7DPchaAycZEYF1SGZCahl2PqtNuS65vjC8kEfY0c6UnZ_7IPI2qPP70ZSHHdgi3PwvoLdelQ", "access_token" : "eyJraWQiOiJmbExOMUZYMGZMMFciLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjbmYiOnsiamt0IjoiSmZCM3FMRzlmYWE0QUp2ZGlsZTlONTJ0U0lQQlU4SWRhTWZFa3BrN3pTSSJ9LCJzdWIiOm51bGwsImF1ZCI6InNvbGlkIiwid2ViaWQiOiJodHRwczovL3BvZC5pbnJ1cHQuY29tL3dybWFjay9wcm9maWxlL2NhcmQjbWUiLCJjbGllbnRfaWQiOiJFMExQTVczeWo2N3FiYVhRUnF3OWpLQzd2QVU2bm51NyIsImlzcyI6Imh0dHBzOi8vYnJva2VyLnBvZC5pbnJ1cHQuY29tLyIsImlhdCI6MTYzMTMyNTgyNCwiZXhwIjoxNjMxMzI3Njg1LCJqdGkiOiI5MzUzYzM2YS00ZjAyLTRhYzAtYmE4NC0zZmQ2YWE5ZDYxYzQifQ.iZGs9AXBJiMJIdgYLTsuio7vQ5b5ULK58M96zhDsyzJ9erztpCA6rckF7NEyJjdBvLU4gUWOs_qYGFKPVtuKzA" }


Userinfo

Now get userinfo by presenting DPoP access token


The request is to: https://broker.pod.inrupt.com/userinfo http method: GET http headers: [ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "dpop": "eyJqd2siOnsia3R5IjoiUlNBIiwiZSI6IkFRQUIiLCJuIjoidDR2d0xSUFlDOXY1X0VJTjhtT0RpR25EV0luWVNVOGV3S05BQUlrd05uWFc5Z2VNT05CZGUwNllGWWpoTmR4bU9KM2xnU1g5M2gyUVRFemlUY05hR18wSU13TFRoVlhUcjlHbFFiTkZUQXlIc3pLMnhTaktVSHE2NnJMWHE5dzJ5MmM4T3g4cjBnMmloLVpsaU53ckFxbHI1OVBqem5Ea2RUS3I5dGF4REZEREZPYXpLYjZBQXE1dGVIMTlGSjBHbzNjZjJwZkh4anUyeEg2Szg5ZFhnV2Roc2dpZ0lTc1NQZFlPbjN0T2xkRUpHZHl6eHlWQ0lxSFRnN1FpMmd4MEtWc1pLbWtkSEUwQ0pzS2s5b2hfTXdZNVJHZE1DUFJnbjRyWGFwRXdNZW5wQnNfU0FuRFZhWE1faU5aamJyN3RwMmZJSGJUZmRzYldNb1hOdTQwTktRIn0sImFsZyI6IlJTMjU2IiwidHlwIjoiZHBvcCtqd3QifQ.eyJqdGkiOiJlYTU3eFN6bTVGaE8wM0tDIiwiaHR1IjoiaHR0cHM6XC9cL2Jyb2tlci5wb2QuaW5ydXB0LmNvbVwvdXNlcmluZm8iLCJpYXQiOjE2MzEzMjU4MjQsImh0bSI6IkdFVCJ9.ZV0bVuPtNyONtPs0zELG9QMhE1dbVm6ohjeYgxVLT6UtLsE8PXXlziqdsg14gd_YvrDVwEDTZO86TM-zGv4bvP-LHEA23jOMER1EcnciuhL6TlzxtIrDIQ16rukbDa1cU_lMZEdnRQb5a4Mzip4GsWgynBwxrQz0f3suBnA3HZWOIbEcXlgptZ-Bqmr9IzbzQ2qDNoPTU6fRhSNv7GtcSPQJXqWFmY6U3dI7rpFjsGa2oAhpZM044_HIBpSYOmEbTv2PpqDdQSN_WChALMu2IjM4nOLUEUwMcdv9LEG63PfyYzqIEhVPZdtpFK60L4n-GhIFNtrHzkDPEIFBvpSYWQ", "Authorization": "DPoP eyJraWQiOiJmbExOMUZYMGZMMFciLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjbmYiOnsiamt0IjoiSmZCM3FMRzlmYWE0QUp2ZGlsZTlONTJ0U0lQQlU4SWRhTWZFa3BrN3pTSSJ9LCJzdWIiOm51bGwsImF1ZCI6InNvbGlkIiwid2ViaWQiOiJodHRwczovL3BvZC5pbnJ1cHQuY29tL3dybWFjay9wcm9maWxlL2NhcmQjbWUiLCJjbGllbnRfaWQiOiJFMExQTVczeWo2N3FiYVhRUnF3OWpLQzd2QVU2bm51NyIsImlzcyI6Imh0dHBzOi8vYnJva2VyLnBvZC5pbnJ1cHQuY29tLyIsImlhdCI6MTYzMTMyNTgyNCwiZXhwIjoxNjMxMzI3Njg1LCJqdGkiOiI5MzUzYzM2YS00ZjAyLTRhYzAtYmE4NC0zZmQ2YWE5ZDYxYzQifQ.iZGs9AXBJiMJIdgYLTsuio7vQ5b5ULK58M96zhDsyzJ9erztpCA6rckF7NEyJjdBvLU4gUWOs_qYGFKPVtuKzA" ] http body:

The response is:

{ "webid" : "https://pod.inrupt.com/wrmack/profile/card#me", "sub" : "wrmack" }

On 11/09/2021, at 3:12 PM, Christopher Prince @.***> wrote:

I made those changes, and the situation remains the same. See below.

I'm wondering if this problem has to do with token endpoint authentication. I have been using a DPoP, but I'm confused about where client_secret_basic vs client_secret_post ought to be used.

Client Authentication: https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication suggests this is: when using the Token Endpoint However, https://solid.github.io/solid-oidc/primer/#authorization-code-pkce-flow-step-14 https://solid.github.io/solid-oidc/primer/#authorization-code-pkce-flow-step-14 suggests to use a DPoP token. These seem conflicting statements.

2021-09-10T21:06:40-0600 debug : requestURL: https://broker.pod.inrupt.com/authorization?code_challenge=2u5UP9TSavD2wmY6_vWilTetglKb2sGMjUWWZk0_dIM&state=ZqiDBMU_SxlcapYtoOphBK-5IGROTvvad_whCNAiOzs&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&response_type=code&scope=offline_access%20profile%20webid%20openid&client_id=AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP&code_challenge_method=S256 https://broker.pod.inrupt.com/authorization?code_challenge=2u5UP9TSavD2wmY6_vWilTetglKb2sGMjUWWZk0_dIM&state=ZqiDBMU_SxlcapYtoOphBK-5IGROTvvad_whCNAiOzs&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&response_type=code&scope=offline_access%20profile%20webid%20openid&client_id=AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP&code_challenge_method=S256 2021-09-10T21:07:35-0600 debug : presentAuthenticationViewController: Optional(biz.spasticmuffin.neebla.demo:/mypath?code=Y9hhGL5v3tbyEg0FYuUQlkAkzjG11e9S&state=ZqiDBMU_SxlcapYtoOphBK-5IGROTvvad_whCNAiOzs); nil 2021-09-10T21:07:35-0600 debug : Sign In Controller succeeded : Response(authResponse: <SolidAuthSwiftUI.AuthorizationResponse: 0x6000028b7200>, parameters: SolidAuthSwiftTools.CodeParameters(tokenEndpoint: https://broker.pod.inrupt.com/token https://broker.pod.inrupt.com/token, jwksURL: https://broker.pod.inrupt.com/jwks https://broker.pod.inrupt.com/jwks, codeVerifier: "WV1CKsCx5LUE0Ltf8xexdjZaD_W7JpkQqQJQGSZ2C8U", code: "Y9hhGL5v3tbyEg0FYuUQlkAkzjG11e9S", redirectUri: "biz.SpasticMuffin.Neebla.demo:/mypath", clientId: "AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP"), storageIRI: nil) 2021-09-10T21:07:35-0600 debug : Controller response: Response(authResponse: <SolidAuthSwiftUI.AuthorizationResponse: 0x6000028b7200>, parameters: SolidAuthSwiftTools.CodeParameters(tokenEndpoint: https://broker.pod.inrupt.com/token https://broker.pod.inrupt.com/token, jwksURL: https://broker.pod.inrupt.com/jwks https://broker.pod.inrupt.com/jwks, codeVerifier: "WV1CKsCx5LUE0Ltf8xexdjZaD_W7JpkQqQJQGSZ2C8U", code: "Y9hhGL5v3tbyEg0FYuUQlkAkzjG11e9S", redirectUri: "biz.SpasticMuffin.Neebla.demo:/mypath", clientId: "AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP"), storageIRI: nil) 2021-09-10T21:08:04-0600 debug : CodeParameters: (base64): Optional("eyJjb2RlVmVyaWZpZXIiOiJXVjFDS3NDeDVMVUUwTHRmOHhleGRqWmFEX1c3SnBrUXFRSlFHU1oyQzhVIiwiY29kZSI6Ilk5aGhHTDV2M3RieUVnMEZZdVVRbGtBa3pqRzExZTlTIiwicmVkaXJlY3RVcmkiOiJiaXouU3Bhc3RpY011ZmZpbi5OZWVibGEuZGVtbzpcL215cGF0aCIsImNsaWVudElkIjoiQVczRWdJbXNWWmNROXZaNkU3UkVpSm56Rkx5dVRwVlAiLCJ0b2tlbkVuZHBvaW50IjoiaHR0cHM6XC9cL2Jyb2tlci5wb2QuaW5ydXB0LmNvbVwvdG9rZW4iLCJqd2tzVVJMIjoiaHR0cHM6XC9cL2Jyb2tlci5wb2QuaW5ydXB0LmNvbVwvandrcyJ9") Passed as htu: https://broker.pod.inrupt.com/token https://broker.pod.inrupt.com/token Body: grant_type=authorization_code&code_verifier=WV1CKsCx5LUE0Ltf8xexdjZaD_W7JpkQqQJQGSZ2C8U&code=Y9hhGL5v3tbyEg0FYuUQlkAkzjG11e9S&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&client_id=AW3EgImsVZcQ9vZ6E7REiJnzFLyuTpVP request: Optional(https://broker.pod.inrupt.com/token https://broker.pod.inrupt.com/token) request.allHTTPHeaderFields: Optional(["DPoP": "eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlJTMjU2IiwiandrIjp7ImtpZCI6ImV4YW1wbGUiLCJ1c2UiOiJzaWciLCJuIjoicXkxS1RGdzVHanRHZ0p1aXV5bFk0UHhmeXM5eGt6VHY5WkJvSkJYT3BRR3JLWGpLcWN4TXgtTEFRMFJWdy1HYnM2LUVtakFUNEVVbk1EN2lwZGxlYW9xcFROTDdUTld0SzRUSmlIbllZNHlrOHRaMG84bHFreGJpOFVOQmdOY3g3N3VTa1d5Rmx2NWZqTll0Q0ZkZ3FnYjlJdlRxOXdJTHZReTU2bGY4TWFfU01OMW1hci1OTlhhRGZtaW9SNm5wX3pKbEFwazBiUlF3SEF0emhGWDlWUXA1YTFnbVdNcE9wVGVYVHF1ck83UDhCM3Ixc2pCYm15R0lBdDdUdzdFRmdEOXk2Q1dOYXBya3RSaDVVUmFVWnVLLVJGNm8ybENnNGs3OWJCUUh2bXJRdE12STh5QlpETm9oUTFSeVlTUHNLY004X1hqLUlTWnNsdVM1c1BaR2ZyWFdqS2sxMkZiMlg2NFZVbjlpVkwtc2RhRHJuamlaUXhZbVNlNEk4YmtIdWJvUW5LVHFrQ3pEZlJjblRrLXp5R0JxakVoN0QzMC1wS054bTQyQTh4TXdrUTlnT0huZmQ5Q3ZWN3FndWVHcFZfbFJQWGU1M1cwbkd6Z1pnQktGNXR1Sms5UWdkd1hxcHRrZXdNVjNwdnp4MGxTTnpBOHY0MnBkUEZNd3JzcEhSNUw1ZEVhenJzTUp1WjhqQUFpeUNOUnNBcFFtZFc1dHUwSndLWDdaa2s2Nlg3cWpPTW8tV1kwOENEMy01TkI5dExRV0FpYnloNHVLMnhoUm9lMFJ3aDF3UWhFQjBXYi1YRTIzOVdwWG5YQTExTFMwSGJBMVhzLVhmQjNROHYtWWVCNDNFY0E4TDdHbU1yejlCWGhyUks2UXpkSFZodHNMM3FjU3pQUlo2UjAiLCJlIjoiQVFBQiIsImt0eSI6IlJTQSIsImFsZyI6IlJTMjU2In19.eyJqdGkiOiI5Njc1M0JENS1CNjhELTQ0ODYtOTJGRS1BRjc3MkFCMDc3REUiLCJodHUiOiJyZXF1ZXN0VHlwZS5iYXNpY3MudG9rZW5FbmRwb2ludC5hYnNvbHV0ZVN0cmluZyIsImlhdCI6MTYzMTMyOTY4NC4yNjcwMDc4LCJodG0iOiJQT1NUIn0.MgxfhvyqTEEq5vcSM1mygjh1fbBNYRPQ3OWr-KI8CMukXPbuQ_luxiqTjw_HKwqVsgyS2nN8yJKLNYJ0wvz1TdcQUKWTrduSLZA90j46_pS8IOcGHMDMn30TSRxV2Y191LpaEgsQjPYsYd4E-orTHeQ8yUqp8NOfASLJZ2Tx5No9jIIlOPB_ilRCgtULKj-TAw8RH61JrhA3EDEHcgNcqhRvJTBWP4L4sdf8kjGQc50i73qX0cYahRYPepY8RxAd5a4GOQ9UZJcLtTWTUAmrXUGuLq2fg4S6k3YlmkIPQnS9dKL1nPzhzE2p4pJCR9IwZFgcPjZykQEzeWrE-KGXXkEJWMmkAUYt6lx0M7Gns74bcEJmMae1eZLTQ57IoWn0wyNdFdg8Py1OKG4j2wz0J_NqtIGNzLxLCfnRdNNuV4dEDC_MpN4wty4PJYr5ih8qSV5Wwu5rPi05563WVE3N6oOIaG-FCdLjBofX9Xb9idUVo_6HKR57lryWgV1oEYjTmkFJDRbMC3c4_5Uu4Jt4zCYqp29gw46RLhg7tFyd6KPlzMuprQIkpFT7JjKW7TaCO1BMyngACODUr5HLENqyhlrONURqA-rzEYbsgpTfcRM_2bomG0JY53f3aJ2lOdwkE-QgLjgma0CFixKKCCZbbNnROu6sUqjwqcmrzRjuqlo", "Content-Type": "application/x-www-form-urlencoded"]) String: Optional("{"error":"invalid_client","error_description":"Invalid client credentials"}") 2021-09-10T21:08:13-0600 error : Failed on TokenRequest: badStatusCode(401)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/crspybits/SolidAuthSwift/issues/3#issuecomment-917327933, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJVC44HRIB3GNPBSEKMBQTUBLCJBANCNFSM5DPHXDYQ.

crspybits commented 3 years ago

Inrupt.net discovery data shows:

{
    "issuer": "https://inrupt.net",
    "jwks_uri": "https://inrupt.net/jwks",
    "response_types_supported": [
        "code",
        "code token",
        "code id_token",
        "id_token code",
        "id_token",
        "id_token token",
        "code id_token token",
        "none"
    ],
    "token_types_supported": [
        "legacyPop",
        "dpop"
    ],
    "response_modes_supported": [
        "query",
        "fragment"
    ],
    "grant_types_supported": [
        "authorization_code",
        "implicit",
        "refresh_token",
        "client_credentials"
    ],
    "subject_types_supported": [
        "public"
    ],
    "id_token_signing_alg_values_supported": [
        "RS256"
    ],
    "token_endpoint_auth_methods_supported": "client_secret_basic",
    "token_endpoint_auth_signing_alg_values_supported": [
        "RS256"
    ],
    "display_values_supported": [],
    "claim_types_supported": [
        "normal"
    ],
    "claims_supported": [],
    "claims_parameter_supported": false,
    "request_parameter_supported": true,
    "request_uri_parameter_supported": false,
    "require_request_uri_registration": false,
    "check_session_iframe": "https://inrupt.net/session",
    "end_session_endpoint": "https://inrupt.net/logout",
    "authorization_endpoint": "https://inrupt.net/authorize",
    "token_endpoint": "https://inrupt.net/token",
    "userinfo_endpoint": "https://inrupt.net/userinfo",
    "registration_endpoint": "https://inrupt.net/register"
}

I'm interested in token_endpoint_auth_signing_alg_values_supported. This seems to suggest DPoP. See https://datatracker.ietf.org/doc/html/rfc8414

crspybits commented 3 years ago

Here is the discovery data for https://solidcommunity.net

{
    "issuer": "https://solidcommunity.net",
    "jwks_uri": "https://solidcommunity.net/jwks",
    "response_types_supported": [
        "code",
        "code token",
        "code id_token",
        "id_token code",
        "id_token",
        "id_token token",
        "code id_token token",
        "none"
    ],
    "token_types_supported": [
        "legacyPop",
        "dpop"
    ],
    "response_modes_supported": [
        "query",
        "fragment"
    ],
    "grant_types_supported": [
        "authorization_code",
        "implicit",
        "refresh_token",
        "client_credentials"
    ],
    "subject_types_supported": [
        "public"
    ],
    "id_token_signing_alg_values_supported": [
        "RS256"
    ],
    "token_endpoint_auth_methods_supported": "client_secret_basic",
    "token_endpoint_auth_signing_alg_values_supported": [
        "RS256"
    ],
    "display_values_supported": [],
    "claim_types_supported": [
        "normal"
    ],
    "claims_supported": [],
    "claims_parameter_supported": false,
    "request_parameter_supported": true,
    "request_uri_parameter_supported": false,
    "require_request_uri_registration": false,
    "check_session_iframe": "https://solidcommunity.net/session",
    "end_session_endpoint": "https://solidcommunity.net/logout",
    "authorization_endpoint": "https://solidcommunity.net/authorize",
    "token_endpoint": "https://solidcommunity.net/token",
    "userinfo_endpoint": "https://solidcommunity.net/userinfo",
    "registration_endpoint": "https://solidcommunity.net/register"
}
crspybits commented 3 years ago

I have singled out these two as they both are supporting the use of DPoP's when making a request to the token endpoint. Though, I don't know if it's the same underlying server code.

wrmack commented 3 years ago

For me, inrupt.com is the only provider that works properly. It uses Enterprise Solid Server. Other providers use the community servers, including inrupt.net. When I register I send "token_endpoint_auth_method" : "none”, but the provider still sends me a client_secret.

When I send a DPoP token request it sends a bearer token though it seems to be properly formed as DPoP. I think there may be a problem with “null” name that we discussed some time ago.

My flow from inrupt.net http://inrupt.net/ is below. I get tokens but it does not complete accessing user info:


Stage 1: Discovery

The app requests the provider's configuration endpoint .well-known/openid-configuration to get information for subsequent requests.

The response is JSON data.

Those providers who conform to the Solid-OIDC protocol will include in the response: "solid_oidc_supported": "https://solidproject.org/TR/solid-oidc"


The request is to: https://inrupt.net/.well-known/openid-configuration

The response is:

{ "id_token_signing_alg_values_supported" : [ "RS256" ], "claim_types_supported" : [ "normal" ], "token_endpoint_auth_signing_alg_values_supported" : [ "RS256" ], "end_session_endpoint" : "https://inrupt.net/logout", "subject_types_supported" : [ "public" ], "claims_parameter_supported" : false, "registration_endpoint" : "https://inrupt.net/register", "grant_types_supported" : [ "authorization_code", "implicit", "refresh_token", "client_credentials" ], "token_endpoint" : "https://inrupt.net/token", "response_types_supported" : [ "code", "code token", "code id_token", "id_token code", "id_token", "id_token token", "code id_token token", "none" ], "require_request_uri_registration" : false, "token_types_supported" : [ "legacyPop", "dpop" ], "issuer" : "https://inrupt.net", "token_endpoint_auth_methods_supported" : "client_secret_basic", "request_parameter_supported" : true, "jwks_uri" : "https://inrupt.net/jwks", "request_uri_parameter_supported" : false, "check_session_iframe" : "https://inrupt.net/session", "authorization_endpoint" : "https://inrupt.net/authorize", "userinfo_endpoint" : "https://inrupt.net/userinfo", "response_modes_supported" : [ "query", "fragment" ], "display_values_supported" : [

], "claims_supported" : [

] }

Remarks

Does NOT include 'solid_oidc_supported' parameter.


Stage 2: Dynamic registration

The client app ("Get tokens") is not already registered with the OpenID Provider. We register the client using OpenID's dynamic registration protocol. A POST request is made using JSON data.

The OpenID Provider responds with a client id.


The request is to: https://inrupt.net/register http method: POST http headers: [ "Content-Type": "application/json" ] http body: { "application_type" : "native", "grant_types" : [ "authorization_code" ], "redirect_uris" : [ "com.wm.get-tokens:/mypath" ], "token_endpoint_auth_method" : "none", "client_name" : "Get tokens", "response_types" : [ "code" ] }

The response is:

{ "grant_types" : [ "authorization_code" ], "registration_access_token" : "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2lucnVwdC5uZXQiLCJhdWQiOiI3M2FmOTVkM2VlYmUyZGJiNzE5OTExMjlmNmYxOWU5NyIsInN1YiI6IjczYWY5NWQzZWViZTJkYmI3MTk5MTEyOWY2ZjE5ZTk3In0.et7kOXkKSkVfqdEl188Per4tn0ia9vy__Wn88ONHtl92b2DiWRxInf_HDKIa_J5dndiZVUhrZrr1JfO3G1Ocif5rCzQwoyK3POGIUxqSAoeUO00Oc2pamb9X2qUgCECfCymN-aFewXG-19lY6AHx8X4qh-OP2EYJEe2P8jY_NUTW-xVcrqeQLtyZ1_B1mmHnsx1T7Nh9OLtxDKgRFa_0dViNa-0hY27i8KPz5ANgSTlSFNDNvn1DiEv3uFDE9L5_c_lvlr-2z3hugyAN1KwQKskm-pZilRgTc5mjsWgVPYtl6DCtM7rfdbxFzAts-Pst747Yd3rB7SGaAmSokn-Q", "id_token_signed_response_alg" : "RS256", "registration_client_uri" : "https://inrupt.net/register/73af95d3eebe2dbb71991129f6f19e97", "client_secret" : "aef85dc14853a83f974df20bbc001f9e", "client_secret_expires_at" : 0, "response_types" : [ "code" ], "client_id_issued_at" : 1631330958, "client_name" : "Get tokens", "application_type" : "native", "token_endpoint_auth_method" : "none", "redirect_uris" : [ "com.wm.get-tokens:/mypath" ], "client_id" : "73af95d3eebe2dbb71991129f6f19e97" }


Stage 3: Get authorization code

A GET request with query. The OpenID Provider provides a login page. After successful login, the provider redirects to the redirect url with a query string appended to the url containing an authorization code.

The app will use the authorization code to request tokens.


The request is to: https://inrupt.net/authorize?client_id=73af95d3eebe2dbb71991129f6f19e97&code_challenge=59ic4Cxf-bb5M4vfvd0qJ-QL59tH_My18pR4bgxYeiw&scope=openid%20profile%20offline_access&response_type=code&state=Mw3rie82eANxTyEM22W-fz6Ufqsd_fJQhm72Kqb2OGI&code_challenge_method=S256&redirect_uri=com.wm.get-tokens:/mypath

Summary - the request's query components:

client_id=73af95d3eebe2dbb71991129f6f19e97& code_challenge=59ic4Cxf-bb5M4vfvd0qJ-QL59tH_My18pR4bgxYeiw& scope=openid profile offline_access& response_type=code& state=Mw3rie82eANxTyEM22W-fz6Ufqsd_fJQhm72Kqb2OGI& code_challenge_method=S256& redirect_uri=com.wm.get-tokens:/mypath

The response is: com.wm.get-tokens:/mypath?code=1ff99..[redacted]..&state=Mw3rie82eANxTyEM22W-fz6Ufqsd_fJQhm72Kqb2OGI

Summary - response components:

code=1ff99..[redacted]..& state=Mw3rie82eANxTyEM22W-fz6Ufqsd_fJQhm72Kqb2OGI

Remarks

Authorization code redacted to avoid malicious use by an attacker who is able to see this display or a copy.


Stage 4: Get tokens

The app makes a POST request using the authorization code.

The OP returns an access_token, id_token and refresh_token can be used for accessing protected resources.


The request is to: https://inrupt.net/token http method: POST http headers: [ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "DPoP": "eyJqd2siOnsiZSI6IkFRQUIiLCJrdHkiOiJSU0EiLCJuIjoiNFpCMlRCS0ZYRnoxRGxKMjdyTy10VlFGV2RWQnpFYngyMEN0d1N6bFdvNnRlNnAzTjhHSFBxSm90dUMxOGliMTFxOG1VSi1hMmNrdzFQQXlJRnpBRkRjYWRJdmRLdW41X3BPTjBnWndtMFhZcDVNd3lNZUo3eGlWdFYxMlREZTVUMkFaNGYtdUVoVXlhWkJ5SHVTS0hTY1hFbnhFTGxOeXR1Y2Q2LVBhUFFMSzNOU3o1QXpnMksxQkVwVzMzVU9YY0FrcC1TeXBHODd4LWQyY1J4b1M3VkU4aUJxcE1laEw4OUs1Q3Q0ZWNlTGVOZ2ota21ncWRqQnNkX3h4aksxVFRGWFhMbTVaUXRJU3VzVlhmOEtMX2M3YmExLVJUTDBOb2hIeWtoNDVOanlSdkxqd1BLdEo1d1B5d2U4SjFkbWxfN182LXFibU9UY214QVpXVGN3MUNRIn0sImFsZyI6IlJTMjU2IiwidHlwIjoiZHBvcCtqd3QifQ.eyJqdGkiOiJORGhZTWwrZ1dhckhQV2tSIiwiaHR1IjoiaHR0cHM6XC9cL2lucnVwdC5uZXRcL3Rva2VuIiwiaWF0IjoxNjMxMzMwOTY5LCJodG0iOiJQT1NUIn0.FjZRDbYS99zn4atx_M1ePQ-V-dSVCMF0j2Aq0BPB8UxsYA_QtkDfsThy_WbrIUHNSRq9-Aytwl0C9iA639d-kD6SiIcDznw-iz6XhlrMYivE-BeX7D4OacQmZDni2ph7MmgldhZHIDeeSlf75N1OTkHgNTCjRKLl7EvPFQx9IpdGSPr31jQrWFzj-hhHHmZKYteRiJ8KBgPlDoR5HH2u8q25arqrxQwR9Z2o9nJ8hrBpGlZ8fKCUDeEMs4dRanZqiJfZyUa4x9XeB6j8-WhNW_psYeTpNlCNl1tcW1eK8WFdVmJEmIIy1UeWHI6p429nAd9fDj9cFQvZwFyrdCRaIA" ] http body: client_id=73af95d3eebe2dbb71991129f6f19e97& redirect_uri=com.wm.get-tokens:/mypath& code_verifier=kVIyNOExRHBttnDC3GvqY2-QCAhBm8e2Io2EVagI1TI& grant_type=authorization_code& code=1ff9978928cf15d407cb77ab9cbfd802

The response is:

{ "access_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6IlJTZFhXUEplV0pJIn0.eyJpc3MiOiJodHRwczovL2lucnVwdC5uZXQiLCJhdWQiOiJzb2xpZCIsInN1YiI6Imh0dHBzOi8vd3JtYWNrLmlucnVwdC5uZXQvcHJvZmlsZS9jYXJkI21lIiwiZXhwIjoxNjMyNTQwNTY5LCJpYXQiOjE2MzEzMzA5NjksImp0aSI6ImNlNzZiMDEwNDZkYjk4NWUiLCJjbmYiOnsiamt0IjoidERTa3pHbUJKYk1HSGItTm1nZ3NPVXFLVmFhU3BMbzcyTkYyNVdERnhzbyJ9LCJjbGllbnRfaWQiOiI3M2FmOTVkM2VlYmUyZGJiNzE5OTExMjlmNmYxOWU5NyIsIndlYmlkIjoiaHR0cHM6Ly93cm1hY2suaW5ydXB0Lm5ldC9wcm9maWxlL2NhcmQjbWUifQ.FynHEr2_vQMQda6zsA5QoqqTbasxBsBwa2OjhuH3LBPCL9F8XY4tG4-JLNBu-BEKX_fNoFFYvI41TQ87k_Vu3q4UFRSRkgLHOJgRuYHvPvKGA0c5lpg5UE9r5Hn1q1qg0eyOZELjL41PMyt0krTLikgD9pGiPr-3ZWXE7edecxxD_CUOBMlNwBc_K8UfLPu-jNzxxOEB_gLFNiHBexuv2x_aIX4MNusb8BYPjs3sT120AaJrIINk61mxOEWyqMiAD8dZxSKlW0-XBSh2AlA9YN8S8olXvKrSmRyd1fuiSbyZONR-lgMTdpLyvRqctZZ48NpmBiha6v687H1-LQjBrg", "expires_in" : 1209600, "refresh_token" : "...[redacted]...", "token_type" : "Bearer", "id_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6ImQ0cWdyOGQ5QWRvIn0.eyJpc3MiOiJodHRwczovL2lucnVwdC5uZXQiLCJhdWQiOiI3M2FmOTVkM2VlYmUyZGJiNzE5OTExMjlmNmYxOWU5NyIsImF6cCI6IjczYWY5NWQzZWViZTJkYmI3MTk5MTEyOWY2ZjE5ZTk3Iiwic3ViIjoiaHR0cHM6Ly93cm1hY2suaW5ydXB0Lm5ldC9wcm9maWxlL2NhcmQjbWUiLCJleHAiOjE2MzI1NDA1NjksImlhdCI6MTYzMTMzMDk2OSwianRpIjoiYWVlZTJmZTZlMzBkOGI5NSIsImF0X2hhc2giOiJhMjZoUXFnamdjTWliM3dFRkM4a29BIn0.HpzJQXOTOyHdDzeICC5JQI1jqXqgU5ll0MwzCy6jORsdNPJ8nPK8gVTPCYpBh4ftJ0ubk1KK-zaVyMfxFsDWVacivnb1PXOH3KlgKnKx6c0_7n0v5tGgl4zOF5wWnIJ1EQEK9h6dH3Dh_6t7lGISaQ2GfHRAg_KhVAKUrKCkOFmCLZxd4wAlVo9ua-udOprQ5r5tp9e6BGAT6BcYhHYZW51_ljVIPHd4mOlMa7-bUg72U0hbUb41UXIy4pcwmO1ZIszVrwHSl6hxZdvmVMSqbMc1hetvYVB1-zFnmir0cTZ7Zi9ADutpkrmAq71RJfI7Ar9JJFBgHJi8kbS-dLsKsw" }

Remarks

Refresh code redacted to avoid malicious use by an attacker who is able to see this display or a copy.


Userinfo

Now get userinfo by presenting DPoP access token


The request is to: https://inrupt.net/userinfo http method: GET http headers: [ "dpop": "eyJ0eXAiOiJkcG9wK2p3dCIsImp3ayI6eyJuIjoiNFpCMlRCS0ZYRnoxRGxKMjdyTy10VlFGV2RWQnpFYngyMEN0d1N6bFdvNnRlNnAzTjhHSFBxSm90dUMxOGliMTFxOG1VSi1hMmNrdzFQQXlJRnpBRkRjYWRJdmRLdW41X3BPTjBnWndtMFhZcDVNd3lNZUo3eGlWdFYxMlREZTVUMkFaNGYtdUVoVXlhWkJ5SHVTS0hTY1hFbnhFTGxOeXR1Y2Q2LVBhUFFMSzNOU3o1QXpnMksxQkVwVzMzVU9YY0FrcC1TeXBHODd4LWQyY1J4b1M3VkU4aUJxcE1laEw4OUs1Q3Q0ZWNlTGVOZ2ota21ncWRqQnNkX3h4aksxVFRGWFhMbTVaUXRJU3VzVlhmOEtMX2M3YmExLVJUTDBOb2hIeWtoNDVOanlSdkxqd1BLdEo1d1B5d2U4SjFkbWxfN182LXFibU9UY214QVpXVGN3MUNRIiwia3R5IjoiUlNBIiwiZSI6IkFRQUIifSwiYWxnIjoiUlMyNTYifQ.eyJqdGkiOiJYTzIrV3lhcnJNcHdcL2pmeCIsImh0dSI6Imh0dHBzOlwvXC9pbnJ1cHQubmV0XC91c2VyaW5mbyIsImlhdCI6MTYzMTMzMDk3MCwiaHRtIjoiR0VUIn0.4VxQJMHs_4UD6v9eKQ9JrOFNFgczNik10Gvso9s_mPDbrfAg9Z0lFVWzanLSuoahLPmUE9p74W_tH3UQzbeEgYYc7pqNloZFNhDUEzwaB2T0n_BkObCjl7SVKHda_oGWAIcxwvzzjRdf-9MVVLsvJvOloLTgqFL3B5LRD6TKcLko4oainoegb2sRXfppj_lbvnk4mTbeOaiHvR6Sp9FqXDslGp20Px5jbVkFYE4nrAoLFfgCLvKzSl4nFQLAYyHdAyig9Yzv6NocxrX8XbBweOQheaKJha8pRWlZMJgLPA-Pa3OwyUHZv6ZW88bhW8edS6txD9IdqOcPtdqxR4UcLg", "Authorization": "DPoP eyJhbGciOiJSUzI1NiIsImtpZCI6IlJTZFhXUEplV0pJIn0.eyJpc3MiOiJodHRwczovL2lucnVwdC5uZXQiLCJhdWQiOiJzb2xpZCIsInN1YiI6Imh0dHBzOi8vd3JtYWNrLmlucnVwdC5uZXQvcHJvZmlsZS9jYXJkI21lIiwiZXhwIjoxNjMyNTQwNTY5LCJpYXQiOjE2MzEzMzA5NjksImp0aSI6ImNlNzZiMDEwNDZkYjk4NWUiLCJjbmYiOnsiamt0IjoidERTa3pHbUJKYk1HSGItTm1nZ3NPVXFLVmFhU3BMbzcyTkYyNVdERnhzbyJ9LCJjbGllbnRfaWQiOiI3M2FmOTVkM2VlYmUyZGJiNzE5OTExMjlmNmYxOWU5NyIsIndlYmlkIjoiaHR0cHM6Ly93cm1hY2suaW5ydXB0Lm5ldC9wcm9maWxlL2NhcmQjbWUifQ.FynHEr2_vQMQda6zsA5QoqqTbasxBsBwa2OjhuH3LBPCL9F8XY4tG4-JLNBu-BEKX_fNoFFYvI41TQ87k_Vu3q4UFRSRkgLHOJgRuYHvPvKGA0c5lpg5UE9r5Hn1q1qg0eyOZELjL41PMyt0krTLikgD9pGiPr-3ZWXE7edecxxD_CUOBMlNwBc_K8UfLPu-jNzxxOEB_gLFNiHBexuv2x_aIX4MNusb8BYPjs3sT120AaJrIINk61mxOEWyqMiAD8dZxSKlW0-XBSh2AlA9YN8S8olXvKrSmRyd1fuiSbyZONR-lgMTdpLyvRqctZZ48NpmBiha6v687H1-LQjBrg", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" ] http body:

ERROR: The request timed out

On 11/09/2021, at 3:27 PM, Christopher Prince @.***> wrote:

Inrupt.net discovery data shows:

{ "issuer": "https://inrupt.net", "jwks_uri": "https://inrupt.net/jwks", "response_types_supported": [ "code", "code token", "code id_token", "id_token code", "id_token", "id_token token", "code id_token token", "none" ], "token_types_supported": [ "legacyPop", "dpop" ], "response_modes_supported": [ "query", "fragment" ], "grant_types_supported": [ "authorization_code", "implicit", "refresh_token", "client_credentials" ], "subject_types_supported": [ "public" ], "id_token_signing_alg_values_supported": [ "RS256" ], "token_endpoint_auth_methods_supported": "client_secret_basic", "token_endpoint_auth_signing_alg_values_supported": [ "RS256" ], "display_values_supported": [], "claim_types_supported": [ "normal" ], "claims_supported": [], "claims_parameter_supported": false, "request_parameter_supported": true, "request_uri_parameter_supported": false, "require_request_uri_registration": false, "check_session_iframe": "https://inrupt.net/session", "end_session_endpoint": "https://inrupt.net/logout", "authorization_endpoint": "https://inrupt.net/authorize", "token_endpoint": "https://inrupt.net/token", "userinfo_endpoint": "https://inrupt.net/userinfo", "registration_endpoint": "https://inrupt.net/register" } I'm interested in token_endpoint_auth_signing_alg_values_supported. This seems to suggest DPoP. See https://datatracker.ietf.org/doc/html/rfc8414 https://datatracker.ietf.org/doc/html/rfc8414 — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/crspybits/SolidAuthSwift/issues/3#issuecomment-917329760, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJVC4YBPQP6PYZBKAHMRFLUBLECVANCNFSM5DPHXDYQ.

crspybits commented 3 years ago

More progress!!! My first token request to https://broker.pod.inrupt.com/token is not failing!

The secret sauce was in how I was doing the "basic auth". I was having lots of confusions. https://solid.github.io/solid-oidc/primer/#authorization-code-pkce-flow-step-14z 1) My first confusion was the use of DPoP in a client request header here. I had gotten success using that method with https://inrupt.net and https://solidcommunity.net. Still not sure what's going on there. i.e., when it's allowable to use DPoP in a client token request header.

2) Then, I was a little confused about how token_endpoint_auth_method operates. My current understanding is that when you give a specific value for token_endpoint_auth_method in the registration request, this is the method you need to use later when making token requests later. Seems obvious in retrospect. But wasn't obvious to me initially.

3) Then, I didn't realize the steps in how to do basic auth. I finally saw the steps in section of 1.4. client_secret_basic. And I'm using that now.

This resulted in a token request that didn't fail.

Here's the result I got:

{
    "access_token": "<snip>",
    "expires_in": 1861,
    "id_token": "<snip>",
    "token_type": "Bearer"
}

I'm uncertain as to why I'm not getting a "refresh_token" back in this result. My request looks like this:

Body: grant_type=authorization_code&code_verifier=T9jQIyEcKgFhEDO2zsZbz8uEvMPvRSYEzkZx0e5BoHQ&code=b8Qnc6dI5jS4DytJDXxF7kPbuQIgMj8e&redirect_uri=biz.SpasticMuffin.Neebla.demo:/mypath&client_id=RggU8ac22GK8hqtnl1PWj9xf2B735XeA

request: Optional(https://broker.pod.inrupt.com/token)

request.allHTTPHeaderFields: Optional(["Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic UmdnVThhYzIyR0s4aHF0bmwxUFdqOXhmMkI3MzVYZUE6MkJjRExqYTI0ZVRpdjVQNVh0VHZrdURaTXNDYkdFSUM="])

crspybits commented 3 years ago

The same exact code setup using https://inrupt.net (and my account there) continues to work as before (when I was using the DPoP header in the token request), and also provides a refresh_token in the token request response.

crspybits commented 3 years ago

The same exact code setup using https://solidcommunity.net (and my account there) continues to work as before (when I was using the DPoP header in the token request), and also provides a refresh_token in the token request response.

wrmack commented 3 years ago

I hadn’t noticed - I don’t get a refresh token either from inrupt.com http://inrupt.com/

For convenience I have put my Get tokens app on the Apple App Store as a Mac OS app. People without Xcode can use it. Visible in NZ store but not sure it is visible in the US - will check.

On 12/09/2021, at 5:55 AM, Christopher Prince @.***> wrote:

The same exact code setup using https://solidcommunity.net https://solidcommunity.net/ (and my account there) continues to work as before (when I was using the DPoP header in the token request), and also provides a refresh_token in the token request response.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/crspybits/SolidAuthSwift/issues/3#issuecomment-917447095, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJVC42VO2S2AKLLMMW6C4DUBOJ2TANCNFSM5DPHXDYQ.

NSeydoux commented 3 years ago

To get a refresh token, the scope should include offline_access, both in the authorization endpoint request (which it looks like it does in the snippets you provided), but also in the client metadata when going through dynamic client registration. Can you verify that it is actually the case ?

wrmack commented 3 years ago

Hi Zwifi

I could not find a requirement to include scopes at registration stage either in OIDC specs or the RFCs.

I get refresh tokens from NSS but not from ESS.

OIDC spec requires a ‘prompt’ parameter for the offline_access scope? section 11 https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess

I haven’t been providing that parameter.

Regards.

Warwick

On 13/09/2021, at 7:05 PM, Zwifi @.***> wrote:

To get a refresh token, the scope should include offline_access, both in the authorization endpoint request (which it looks like it does in the snippets you provided), but also in the client metadata when going through dynamic client registration. Can you verify that it is actually the case ?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/crspybits/SolidAuthSwift/issues/3#issuecomment-917900893, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJVC43LO3YFVLP42EQN7W3UBWPFFANCNFSM5DPHXDYQ.

NSeydoux commented 3 years ago

My bad, I was thinking about the grant_types: https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata. I suspect that for a client registered with only authorization_code in its grant types (i.e. without the refresh_token grant type), the OIDC provider could choose not to return a refresh token, as the client would not be able to use it anyway.

Regarding the prompt, indeed it is mandatory to provide a prompt=consent parameter, but I believe this is the default value, so some OIDC providers may decide to ignore it being omitted. Providing a conflicting value (e.g. prompt=none), however, could result in an error.

wrmack commented 3 years ago

That worked. Many thanks.

On 13/09/2021, at 8:31 PM, Zwifi @.***> wrote:

My bad, I was thinking about the grant_types: https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata. I suspect that for a client registered with only authorization_code in its grant types (i.e. without the refresh_token grant type), the OIDC provider could choose not to return a refresh token, as the client would not be able to use it anyway.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/crspybits/SolidAuthSwift/issues/3#issuecomment-917963639, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJVC43KUUD2THKMUMIO47TUBWZHZANCNFSM5DPHXDYQ.

crspybits commented 3 years ago

That works for me too! Thanks!

crspybits commented 3 years ago

One further question @NSeydoux: I just want to confirm that I cannot get an id token (or access token) back from the request to https://broker.pod.inrupt.com/authorization? I ask this because I have been getting an id token from some other issuers on an authorization request. (e.g., https://solidcommunity.net). Thanks!

wrmack commented 3 years ago

Subject to advice from @NSeydoux I suspect your response_type might be [“code”, “id_token”] instead of just [“code”].

On 14/09/2021, at 4:15 PM, Christopher Prince @.***> wrote:

One further question @NSeydoux https://github.com/NSeydoux: I just want to confirm that I cannot get an id token (or access token) back from the request to https://broker.pod.inrupt.com/authorization? I ask this because I have been getting an id token from some other issuers on an authorization request. (e.g., https://solidcommunity.net https://solidcommunity.net/). Thanks!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/crspybits/SolidAuthSwift/issues/3#issuecomment-918785410, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJVC43H6ZDHLHARV7XZARTUB3D5HANCNFSM5DPHXDYQ.

NSeydoux commented 3 years ago

@wrmack that would be correct if hybrid flows were supported by https://broker.pod.inrupt.com, which isn't the case, while it is true for https://solidcommunity.net, which explains the different behaviours.

@crspybits you are correct: the typical authorization code flow is split in two phases, one during which front-channel interaction enables the client to get an authorization code (and no tokens), and one during which back-channel interaction enables the client to exchange this authorization code for tokens (ID, access, and refresh if applicable). Other flows exist, such as the implicit flow, in which access tokens are returned directly after the redirection from the authorization endpoint (i.e. no backchannel interaction), but this has some security flaws that make it undesirable in many use cases.

crspybits commented 3 years ago

OK-- thanks. I ask this because I'm trying to work out a general purpose mechanism (ie., across Solid Pod providers) regarding what I can send to my custom server. My custom server needs an id token (or an access token) for endpoint authentication. It will also be making Solid Pod resource requests and so needs an access token, and a refresh token to keep that access token up to date.

So, to accommodate all the cases, I think what I need to do is:

  1. On my mobile client after the /authorization endpoint request, in all cases I'll make a /token request which will give me a refresh token and ensure I have an id token. [When I initially wrote this I was forgetting that this /token request can use or should use client_secret_basic-- also see below]. I will not have to have a public/private key pair on the client in this use case.

  2. I'll send various items to my custom server in my initial account creation request to it including an id token for endpoint authentication (i.e., to verify to the custom server that the user of the custom server endpoint is valid) the refresh token, the users storage IRI, and the pod issuer URL. Given that client_secret_basic was used to create the refresh token, I'm assuming I'll then have to use client_secret_basic to use the refresh token in creating access tokens. That means I'll have to pass the client secret up from the client to the custom server.

  3. My server is going to use a (basically static) public/private key pair to do its subsequent resource requests. I.e., when generating DPoP's to make those resource requests.

Some observations:

A. It seems a little odd to be passing the client secret up to the custom server. I would have thought this was something that just stayed on the mobile client.

B. I'm confused about the use of DPoP's indicated in https://solid.github.io/solid-oidc/primer/#authorization-code-pkce-flow-step-14. See also https://forum.solidproject.org/t/the-use-of-dpop-in-the-token-endpoint/4664