Skip to content
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

Authorize endpoint promise hangs Until timeout #333

Open
rishijung377 opened this issue Jan 31, 2025 · 7 comments
Open

Authorize endpoint promise hangs Until timeout #333

rishijung377 opened this issue Jan 31, 2025 · 7 comments

Comments

@rishijung377
Copy link

Specify your setup

  • Operating System:
    Mac OS
  • Node version:
    v23.3.0
  • npm version:
    11.0.0
  • version of @node-oauth/oauth2-server
    5.2.0
  • which OAuth2 workflow:
    Grant Flow: "authorization_code"
  • at which workflow step does the error occur:
    Authorizatio flow

Describe the bug

Issue: After saving the authorization code, the response does not redirect with the redirect_uri and state parameter. Instead, the Promise hangs indefinitely.

Expected Behavior: The server should redirect to the provided redirect_uri with the state parameter after successfully saving the authorization code.

Observed Behavior: The process stalls, and the redirect does not occur.
Return data from authorize()

{
  authorizationCode: '6ac10a0b8a4f40f326646946308af63438bcb303c1ae5b021e26c265e183bcbc',
  client: {
    clientId: '12345',
    clientSecret: 'secret',
    grants: [ 'authorization_code' ],
    redirectUris: [ 'http://localhost:3003/secret' ]
  },
  user: { name: 'Rishi', _id: 1 }
}

Response Object:

Response {
  status: 302,
  body: {},
  headers: {
    location: 'http://localhost:3002/secret?code=f8db24809f8779d051f1d8a2c3a73e06a1689a81e6921550a6094ef170389bdb&state=ssotest'
  },
}

To Reproduce

Steps to reproduce the behavior:
Npm install with mentioned version, create a sample app with authorization grand type, the redirect does not happen
Alternatively, please add a link to a GitHub repo
that reproduces the error/s.

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

Add any other context about the problem here.

@jankapunkt
Copy link
Member

Thank you @rishijung377 for reporting. I have some follow-up questions. First, did you encounter any error/warning in the consoles?

What was the exact last call, when the promise stalls and does not resolve? Can you paste a minimal code example, especially with the model implementation you used, please?

I also see you pasted a response object. Once the client receives this response it should redirect.

FInally, we have covered this in our integration tests, here:

https://github.com/node-oauth/node-oauth2-server/blob/4e40cc878efe96b756aa441c4d458087d05d6c64/test/integration/handlers/authorize-handler_test.js#L310..L360

Is there anything you can spot that might help you?

@rishijung377
Copy link
Author

Thank you @jankapunkt for the response. I have tried to answer all your queries, let me know if additional information is required.

Thank you @rishijung377 for reporting. I have some follow-up questions. First, did you encounter any error/warning in the consoles?

There is no any error logs. As stated earlier, the application does not route to the redirect url, and it keeps on loading. I followed the code flow, and the updateResponse does set the response to the redirect URL(hence the response object....)

What was the exact last call, when the promise stalls and does not resolve? Can you paste a minimal code example, especially with the model implementation you used, please?

I created a very simple code snippet where I was able to reproduce the error. This is not the full application setup, as it is missing token implementation. But the main gist of this sample application to show that the application does not gets routed to ${redirectURL}?code=``

const authCode = {};

const model = {
  getClient: async () => {
    return {
      clientId: '12345',
      clientSecret: 'secret',
      grants: ['authorization_code'],
      redirectUris: ['http://localhost:3003/secret']
    }
  },

  saveAuthorizationCode: async (code, client, user) => {
    authCode[code] = { code, client, user }
    return { authorizationCode: code.authorizationCode, client, user }
  },

  getAccessToken: async (code) => {
    return authCode[code]
  }
};

app.oauth = new oauthserver({
    model,
});

const checkAuthGrant = async (req, res, next) => {
  console.log('Hello from check auth grant')
  // note that all these are hard-coded for now
  req.query.client_id = '12345';
  req.query.redirect_uri = 'http://localhost:3003/secret';
  req.query.state='ssotest';
  req.query.response_type = 'code'
  req = new oauthserver.Request(req);
  res = new oauthserver.Response(res)

  const authRequest = {
    authenticateHandler: {
      handle: () => {
        return {
          name: 'Rishi',
          _id: 1
        }
      }
    }
  }
  const x = await app.oauth.authorize(req, res, authRequest);
  console.log(x);
  console.log(res.headers.location);
  console.log(res.status);
// the application keeps on hanging at this stage.
}

app.get('/', checkAuthGrant, function (req, res) {
    console.log(res);
});

app.all('/secret', (req, res) => {
  res.send('secret area')
})

I also see you pasted a response object. Once the client receives this response it should redirect.
Finally, we have covered this in our integration tests, here:
https://github.com/node-oauth/node-oauth2-server/blob/4e40cc878efe96b756aa441c4d458087d05d6c64/test/integration/handlers/authorize-handler_test.js#L310..L360

I saw the integration test, and I do have the same headers as in the integration tests, but I am not routed to the redirect URL. Logically, if the response has the correct Location header and status code, the redirect should work, right? However, it's not working here. Note that redirects work fine in other parts of the application—for example, in the auth flow, users without credentials are correctly redirected to the login page.

@shrihari-prakash
Copy link
Contributor

shrihari-prakash commented Feb 5, 2025

Hello @rishijung377,

As I understand, the library in itself does not send any response to the client (matter of fact, it doesn't even assume what framework you use to build the server).

You would need to get the code and redirect it yourself:

/// rest of your code
const code = await app.oauth.authorize(req, res, authRequest);
const url = new URL(req.query.redirect_uri);
url.searchParams.set("code", code.authorizationCode);
url.searchParams.set("state", (req.query.state) || "abc");
return res.redirect(url.toString());

@rishijung377
Copy link
Author

rishijung377 commented Feb 5, 2025

Hello @rishijung377,

As I understand, the library in itself does not send any response to the client (matter of fact, it doesn't even assume what framework you use to build the server).

Hey @shrihari-prakash, I do not think that is the case. Check this code here https://github.com/node-oauth/node-oauth2-server/blob/master/lib/handlers/authorize-handler.js#L366. The package is setting the response to the redirect uri and making the redirect.
Anyways, I did try to route the application to the redirect url manually, It did not redirect to the required URL
redirect uri created from provided code snippet.
http://localhost:3003/secret?code=da1bee50dcf7c5f8403183bee948db511c5d625a25a32a9dfdd346525dc6a0b7&state=ssotest

@shrihari-prakash
Copy link
Contributor

Hmm I just noticed the integration test sent by @jankapunkt as well... Looks like the status was indeed supposed to be set to a redirect.

About the manual redirect, what was your expectation? To me, what you pasted in your comment looks correct with code and state in the URL specified in the req.query.redirect_uri variable?

@rishijung377
Copy link
Author

Hmm I just noticed the integration test sent by @jankapunkt as well... Looks like the status was indeed supposed to be set to a redirect.

About the manual redirect, what was your expectation? To me, what you pasted in your comment looks correct with code and state in the URL specified in the req.query.redirect_uri variable?

The expected redirect does not happen and the application keeps on loading indefinetly

@shrihari-prakash
Copy link
Contributor

shrihari-prakash commented Feb 5, 2025

@rishijung377 in that case, I think the problem is that you are overriting the express req and res objects with the ones in the library directly. By doing this, you lose all the functionalities like res.redirect. Consider doing something like:

const checkAuthGrant = async (req, res, next) => {
    console.log('Hello from check auth grant')
    req.query.client_id = '12345';
    req.query.redirect_uri = 'http://localhost:3003/secret';
    req.query.state='ssotest';
    req.query.response_type = 'code'
    const request = new oauthserver.Request(req);
    const response = new oauthserver.Response(res);
  
    const authRequest = {
      authenticateHandler: {
        handle: async () => {
          return ({
            name: 'Rishi',
            _id: 1
          })
        }
      }
    }
    const code = await app.oauth.authorize(request, response, authRequest);
    const url = new URL(req.query.redirect_uri);
    url.searchParams.set("code", code.authorizationCode);
    url.searchParams.set("state", req.query.state);
    console.log("Redirecting to", url.toString());
    return res.redirect(url.toString());
 }

This way, you are not overwriting the references permanently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants