panva / openid-client

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

Processing Callback section of README not clear to me #150

Closed tetchel closed 5 years ago

tetchel commented 5 years ago

The Processing Callback README sections is as follows:

const { state, response_type } = session[authorizationRequestState];
client.authorizationCallback('https://client.example.com/callback', request.query, { state, response_type }) // => Promise
  .then(function (tokenSet) {
    console.log('received and validated tokens %j', tokenSet);
    console.log('validated id_token claims %j', tokenSet.claims);
  });

What is session[authorizationRequestState]? I understand the state and response_type parameters (I suppose here the response_type would be token or token id_token?), but what is request.query? Does this method actually perform the request to the authorization endpoint and handle the callback, or just the second part? All the examples of this library's usage I've found are from the server side, using this library together with passport and a Strategy, and don't actually need client.authorizationCallback. I want to use the library from a native application, where I'm not using passport, and don't have any kind of session cookie (I do have my state and nonce). I have the steps up to the authorization callback working fine, but am stuck on this step, in particular what to pass for request.query. Please let me know if this is supported and how I can use it!

panva commented 5 years ago

In general this is not the place to get help about HOW oidc/oauth works.

Anyway, you can use this helper to get the callback params object from your express request https://github.com/panva/node-openid-client/blob/master/README.md#handling-multiple-response-modes

You should also have a session middleware to store a randomly generated state that you sent with the authorization request as that is important to protect yourself from various attacks on oauth.

You can also open the passport strategy to get a peak at how it all ties together.

This is also a good wip package that abstracts the protocol from you, you may inspire yourself from it https://github.com/auth0/express-openid-connect

tetchel commented 5 years ago

I'm sorry, I don't understand how your response relates to my questions. I know how OIDC works; I have it working without any library but I'd rather use your library if I can figure out how this particular function is meant to be used. I don't have any session middleware, or any middleware at all, because I am not a server, I am a native desktop application. With this in mind, can you help me answer these two questions:

  1. What should I pass as the second parameter? In the example I copied above it is request.query, but I don't know what would replace this in my use-case.
  2. Does the authorizationCallback function actually perform the request to the authorization endpoint and handle the callback, or just the second part? IE, must I do the POST to the URL obtained from client.authorizationUrl, or is it done for me when I call authorizationCallback?
panva commented 5 years ago

1) since you’re versed with oidc then pass an object with the authorization callback params like code, state, etc

2) it’s processing a callback, not triggering it. There’s no function to do that.

Being in a native desktop app does not excuse not having a state imho.

panva commented 5 years ago

I'm sorry, I don't understand how your response relates to my questions.

Providing your actual environment and these details would have certainly helped more then repeating that you “just don’t understand”. You must not be surprised to get a reaponse like this with the lack of input and the general assumption this library is consumed from a node web server.

tetchel commented 5 years ago

You must not be surprised to get a reaponse like this with the lack of input and the general assumption this library is consumed from a node web server.

That is of course fair but I did specify in my original issue report that I am not using a node web server

I want to use the library from a native application, where I'm not using passport, and don't have any kind of session cookie (I do have my state and nonce).

panva commented 5 years ago

You could be not using a lot of things so that information has zero value to me as the person trying to help. Just sayin. Hope it’s clearer to you now.

tetchel commented 5 years ago

OK I got around to trying this out and it was pretty easy after all I just had to think about it a bit more. I'm commenting it here anyways in case anyone else comes across this issue.

The second parameter is an object with the actual values returned in the callback querystring. In my case, it was the state and the code.

The third parameter is an object with the expected values to be verified. In my case, this was the state, nonce, and response_type.

Snippet:

const redirectUri = "vscode://publisher.extension/authcb"; 
const responseType = "code";
const authUrl = client.authorizationUrl({
    redirect_uri: redirectUri,
    scope: "openid",
    grant_type: "authorization_code",
    response_type: responseType,
    nonce: nonceParam,    // a string
    state: stateParam,    // also a string
});
// ... open the authUrl, have the user log in, etc... 
// then when auth code callback is received, I store it as callbackUri
const qs = require("querystring");
const query = qs.parse(callbackUri.query);
// query object is expected to have "state" and "code" attributes

const checks = {
    state: stateParam,
    nonce: nonceParam,
    response_type: responseType,
};

// will reject if any of the checks fail (eg. state/nonce mismatch)
const tokenset = await client.authorizationCallback(redirectUri, query, checks);

Thanks for the great library.