oauthjs / node-oauth2-server

Complete, compliant and well tested module for implementing an OAuth2 Server/Provider with express in node.js
https://npmjs.org/package/oauth2-server
MIT License
4.02k stars 931 forks source link

Getting authorization_code fails due to missing access_token?!? #358

Open p-bakker opened 7 years ago

p-bakker commented 7 years ago

Hi,

I'm trying to get node-oauth2-server going. I've got the latest version installed and have this code oauth.authorize(request, response) .then(function(success) { res.end(JSON.stringify(success)) }).catch(function(err) { response.statusCode = err.code || 500 res.end(JSON.stringify(err)) })

When this code is called with a request with the queryString response_type=code&client_id=CLIENT_ID&redirect_uri=http://www.someurl.com&scope=read I get the following error returned: {"message":"Unauthorized request: no authentication given","code":401,"name":"unauthorized_request"}

I've traced this into the code and it seems it is coming from the this.getUser(request, response) call on line 88 in authorize_handler.js, which calls this.authenticateHandler.handle, which calls this.getTokenFromRequest(request), which in turn looks foor the access_token, which I'm not sending in, so the thing bombs out.

Now, I'm not getting this at all. To my knowledge, when requesting an authorization code in oAuth2, I'm not supposed to send in an acces token, as the sole purpose of getting an autorization code is my client can then do a call to exchange the code for an access token. Or am I missing something?

Any insight appreciated.

Must say it's tough going with v3 documentation and samples not yet in place. Hope they'll be available soon

p-bakker commented 7 years ago

Think I have the answer to this problem: #264

Makes sense that somehow in the authorize flow I need to determine the user and the default AuthorizeHandler will of course choke if my authorize page doesn't use oAuth for authorization itself.

Will fiddle with it to see if I can get things going with a custom AuthorizeHandler

slavab89 commented 7 years ago

So did you manage to work around this? I've too read the other issue that you've linked but i'm not sure how the entire flow should work.

Say i want a user to login. I first go to request a authorization_code. If i get back an error then i understand that i probably need to show the user a login screen (for the username and pass) and do a 'password' grant..?? After that i have the access token so why would i need to do the authorization code flow?

What i'm trying to accomplish in my application is the following: I have a web page, i want the user to click login button. Put his username and password and login to the system. Simple right? The thing is that i want it to happen with OAuth (am i even right in thinking?) Why? Because that web page is running on a nodejs express server that i can authenticate against a "authorization server" that's running elsewhere. Something like this: https://dglozic.files.wordpress.com/2014/10/micro-authentication.png

Tell me if it makes sense or if this module is not really for me hehe

cirick commented 7 years ago

I was able to get this to work with a custom authentication handler for the authorization step when trying to generate the authorization code. Obviously you don't want to do this override for actual API authentication as the default behavior of looking up based on access_token is ok. If anyone else has a better way would be good to know.

router.post('/oauth2/authorize', (req, res, next) => {
    const options = {
        authenticateHandler: {
            handle: (data) => {
                // Whatever you need to do to authorize / retrieve your user from post data here
                return {id: userId};
            }
        }
    }
    // Include options to override
    oauth.authorize(request, response, options);
}
orff commented 7 years ago

@cirick you saved me hours, I was stuck on EXACTLY the same. I think I wasted 5-10 hours before I found this post. Thanks ! The docs on this part are awful and/or non-existent.

jonbronson commented 7 years ago

I just hit this same issue and thankfully found this thread. Is adding a custom authenticateHandler considered the "preferred" solution to this?

mjsalinger commented 7 years ago

Yes, it is. The idea of this library is that it handles the OAuth, not the authentication. So the general flow is that the request is submitted (for authorization_code grant it's the auth grant request) and then the app code implements the authentication. Once authentication is done, you call authorize to generate the grant code. The oauth2 library initiates a call to the authenticationHandler to validate that the authentication.

The password grant authentication is an optional "let the library handle the authentication" functionality, which fits some use cases, but most will be using the handler.

jonbronson commented 7 years ago

Thank you! Explanation makes perfect sense. Providing the handler gets rid of the 401 Unauthorized and a code is generated.

Is the intended behavior of node-oauth2-server's authorize() endpoint to do a server-side redirect to to the redirect-uri? When I send a POST to my oauth/authorize endpoint, I can verify the entire authentication code flow operates, but instead of returning an authcode and state, the server is triggering a GET request on the redirect_uri (along with authcode and state query params) and returning the HTML of that page. I'm using the express-oauth2-server wrapper, so not sure if that behavior is something triggered by the wrapper or by this library. But it doesn't seem to match how I believed OAuth2 to function.

If the oauth.authorize() endpoint does a server-side redirect, then the POST request has to be made using an html form, instead of an ajax request. But then there's no way to set a JWT bearer token in the header to authenticate which user is making the request to generate an auth code. What am I missing?

willin commented 6 years ago

https://github.com/oauthjs/node-oauth2-server/blob/master/lib/handlers/authorize-handler.js#L235-L246

why not use Model functions?

tylerjbainbridge commented 6 years ago

@jonbronson Did you ever figure this out? I'd like to have the server respond with an auth code and redirect URI and let the client requesting a code handle the actual redirecting.

suryateja648 commented 4 years ago

@cirick , tanks your solution solved my problem.