panva / openid-client

OAuth 2 / OpenID Connect Client API for JavaScript Runtimes
MIT License
1.83k stars 392 forks source link

Hybrid Flow #118

Closed sero323 closed 6 years ago

sero323 commented 6 years ago

Hey,

I got a question regarding implementing a hybrid flow. I am curious as to how the client is setup. I am calling the getAuthURL() to get the authorization end point with all the parameters and once i'm there, i log in and i do get a the following response...

{ code:  '134f35993a492806b4373a1f028ef6421d579e3ff7b7da2140178a80c8ded963',
id_token: 'eyJhbGciOiJSUzI1NiIsImtpZCI6ImEwN2FiY2M5NTM0NTlhODE5NWMwZTZkMjBhODQ1NWVjIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MzY5NjQwNDUsImV4cCI6MTUzNjk2NDM0NSwiaXNzIjoiaHR0cHM6Ly9kZW1vLmlkZW50aXR5c2VydmVyLmlvIiwiYXVkIjoic2VydmVyLmh5YnJpZCIsIm5vbmNlIjoiM0JUZlRTaGF6VTJHMTcrWmNJcFdpZz09IiwiaWF0IjoxNTM2OTY0MDQ1LCJjX2hhc2giOiJNclRTSVVYRjBNNF94OUVpYXNNSERnIiwic2lkIjoiMTU4NzBlNzY0MGMyYmQzZGNlM2RiYjg1NzUyODBmZjciLCJzdWIiOiI4ODQyMTExMyIsImF1dGhfdGltZSI6MTUzNjk2NDA0NSwiaWRwIjoibG9jYWwiLCJhbXIiOlsicHdkIl19.bMdbPDHF3omy5cSVO5-8z3Ceyuxu_QlczQXIJ-aeCjJaxxVDx44QfTXHW0eii-_9hxViAgHK-m1E9rTu9Dr8tzHUVw2KJJL7NHuRoOJe4LpJAvcUdznqyRiU_IFrxr7k2SBeGMjWvLWujTMW53VDuS2_-i2O0P2R2Tz-wEd5QHFR5M8BrZqowLWNKqT2FEOZ_JWgQRWSXTUa39Ho2W2iVmMkqTHE2UT8o59xwifJsRSVsWE_Z93SfY6yiLf65kB7ygj0OCa2GTpKYJwwOAEcqrFft0oFHyzlJeBmOf864jTmOPf8JzASbMPPRobRMQIP2DFYBY_Yl3infUSAbCGFVg',
scope: 'openid profile email api',
state: '3BTfTShazU2G17+ZcIpWig==',
session_state: 'pa9r67nSfZSFQh2kjgltFCOoDZ-7ozDdiXHLeJvXcGo.2b7713d8167ada041205c0c38917e635' }

until i get to the authorizationCallback point. Then i get an 'invalid_client' error. I tracked it down further and it seems to be coming from the authenticatedPost method. I am trying to integrate with: https://demo.identityserver.io/.well-known/openid-configuration

Any ideas as?

const dp = new OIDCClient({
    client_id: 'server.hybrid',
    client_secret: '2BB80D537B1DA3E38BD30361AA855686BDE0EACD7162FEF6A25FE97BF527A25B',
    redirect_uri: 'https://localhost:8080/callback',
    nonce: '9c158bae3758',
    scope: 'openid profile email api',
    response_type: 'code id_token',
    response_mode: 'form_post',
    state: '3BTfTShazU2G17+ZcIpWig=='
});
panva commented 6 years ago

1) where is this ‘new client’ snippet from? 2) if you have a problem with an idp its likely that you’re not authenticating properly (aligning token endpoint auth method configured on the server or the client) or there’s a problem with your idp and you should check its logs first since that invalid_client is just something taken from the IdP response. 3) has nothing to do with a hybrid flow

Besides configuring a client correctly there’s nothing more I can suggest other than reaching out to the IdP for more details.

sero323 commented 6 years ago

K. I will try to see the output of the logs on the IdP. Is there a way we can change the request body of the token endpoint?

panva commented 6 years ago

that last sentence, can't somehow parse that.

sero323 commented 6 years ago

In other words, when the authenticatedPost method is called it sets the body of the request to be sent to the /token endpoint. Can we overwrite or add parameters to be sent to the /token endpoint? My token endpoint requires the client_id to be sent along with code, grant_type, redirect_uri.

panva commented 6 years ago

https://github.com/panva/node-openid-client/blob/master/README.md#configuration

ahall-medullan commented 6 years ago

I have a similar issue, when we use form_post it seems identityserver4 is sending back all the correct parmeters after the authentication except the nonce. so its not this library that is at fault.

panva commented 6 years ago

Again, can you please point out WHERE this snippet is coming from?

const dp = new OIDCClient({
    client_id: 'server.hybrid',
    client_secret: '2BB80D537B1DA3E38BD30361AA855686BDE0EACD7162FEF6A25FE97BF527A25B',
    redirect_uri: 'https://localhost:8080/callback', // not a registered IANA client metadata
    nonce: '9c158bae3758', // not a client property 
    scope: 'openid profile email api', // not a client property
    response_type: 'code id_token', // not a client property
    response_mode: 'form_post', // not a client property
    state: '3BTfTShazU2G17+ZcIpWig==' // not a client property
});
panva commented 6 years ago

Everything works as intended with the identityserver.io demo issuer. 5 minutes worth of coding here, visit http://localhost:3000 via GET to trigger auth, uses form_post so the POST route will consume the callback. No problem to be seen. Neither with nonce, nor with client authentication.

sero323 commented 6 years ago

The code above is a node.js implementation. The OIDCClient is just a class i created to store certain functions like ending sessions initializing the client etc... I was not aware the client was doing the hashing on client_secret for me (or is it? does it get sent to the IDP and the IDP will check it with a hash? Not sure). The solution for me was to use the plain text secret and it worked marvelously. Thanks @panva. Your library is awesome.

panva commented 6 years ago

I was not aware the client was doing the hashing for me (or is it? does it get sent to the IDP and the IDP will check it with a hash? Not sure).

What hashing are thinking of? 🤔

sero323 commented 6 years ago

For the client_secret

panva commented 6 years ago

I'm fairly certain you won't be able to point me to a specification that defines something like this.

sero323 commented 6 years ago

Well I'm not sure what the specification is. So I'm assuming the client does not do the hashing? The IdentityServer4 Demo config, shows that the client_secret is hashed, so i assumed I had to hash it so the client_secret will match. But i was wrong. Here's the client config on the IdentityServer4 Demo: https://github.com/IdentityServer/IdentityServer4.Demo/blob/master/src/IdentityServer4Demo/Config.cs#L59

panva commented 6 years ago

You're looking at server internals, what's key is https://demo.identityserver.io/ where it says the client secret is "secret".

If i had to guess, identityserver actually doesn't store the secrets in plaintext but instead stores their hashes. This is fine so long as they don't enable client_secret_jwt auth or dynamic registration management.

sero323 commented 6 years ago

If i had to guess, identityserver actually doesn't store the secrets in plaintext but instead stores their hashes. This is fine so long as they don't enable client_secret_jwt auth or dynamic registration management.

That makes sense.