ChatGPT解决这个技术问题 Extra ChatGPT

Facebook OAuth 2.0 "code" and "token"

Why do you need both a "code" and a "token" in the Facebook OAuth2 authentication flow as described here: https://developers.facebook.com/docs/authentication/ ?

If you look at the OAuth dialog reference (https://developers.facebook.com/docs/reference/dialogs/oauth/), it seems like you only ever use the token to fetch information about the user, and if you specify the response_type parameter as token or code,token, then you get the token on the first time.

Why do you need to get a "code" and then use the code to get a "token" as opposed to getting the token directly?

I guess I'm misunderstanding something basic about how OAuth works, but it seems you avoid the request to https://graph.facebook.com/oauth/access_token entirely if you get the token the first time with the dialog.


r
rofrol

Let us take a simple example to differentiate authentication code vs access token.

You as a user want to try a new Facebook app called Highjack. So you click on the application and the Highjack app asks you to log into your Facebook account. When you are done, Facebook generates an authentication code for you.

This code is then passed to the Highjack server which uses its own FB client id, FB secret and your authentication code to get an access token.

In the above example the authentication code is confirming you as a user is a valid FB user. But the second steps says "you as a FB user is giving access to the Highjack app for certain resources".

If the Highjack app wanted implicit grant (i.e direct access token), then the access token would be visible to you also since it is being exchanged with the browser. This means you can now call all Facebook APIs on behalf of Highjack using the access token. (You can only use the access token to get your personal information but Facebook has no way of knowing who is calling their APIs.)

Since we have 2 parties (You and Highjack) authenticating with Facebook we have this 2 fold mechanism.


A very clean description !
Do you have a real-world scenario where Highjack wouldn’t want the user to call the Facebook api on behalf of it? For a simple “login with Facebook” usecase, both ways are ok because Highack’s server only needs a token from the user to check that it is valid and to get the user’s Facebook id (to find it in the DB). In this case it doesn’t matter if the token is also in the hands of the user (The only permission that this token has is to ask “what’s the user’s Facebook id?”). Right?
There is one clarification to this explaining to avoid misunderstanding. This OAuth2 flow consists of two steps not to separate user authentication and client authorization, but by security reasons. This is the most important reason of segregeation of these two steps (auth code getting and access token getting). Please, take a look to the answer below from 'Michael R' with great video from Nate Barbettini.
@Oren when a third party wants to see a users analytics i.e. someone going on social blade to see others analytics, social blade needs access to a said users analytics and the user isnt around to provide them with an access token, therefore a longlived token is acquired by social blade in exchange for the users short lived token earlier on and stored on their db, so social blade can have access any time without the user needing to log in to facebook and give them access (im guessing thats how it works anyway)
Sorry, this answer is not very complete. It doesn't mention the important security difference between "front channel" and "back channel" as mentioned in the video in Michael R's answer.
D
Drew

Borrowed shamelessly from Salesforce Documentation:

Authorization Code

An authorization code is a short-lived token representing the user's access grant, created by the authorization server and passed to the client application via the browser. The client application sends the authorization code to the authorization server to obtain an access token and, optionally, a refresh token.

Access Token The access token is used by the client to make authenticated requests on behalf of the end user. It has a longer lifetime than the authorization code, typically on the order of minutes or hours. When the access token expires, attempts to use it will fail, and a new access token must be obtained via a refresh token.


Why the use of both? What are the advantages of each? Is it only because of lifetime? Could you expand this answer a bit, please, as it doesn't really answer the OP.
@Anoyz, they have different purposes. Web application needs Authorization Code to get from authorization server Access Token, and it needs Access Token to authenticate its access to the user's resources on their behalf.
Just copy the definition from the official site makes no sense at all. Please tell the reason why we need an Authorization Code to get the Access token instead of geting the Access token directly.
see my answer below, hope that help.
@arganzheng because if we were to just have one token this would mean if someone intercepted that token, then they could use it anywhere any time. However when the shortlived token is passed to the client, the client then passes the short lived token to be authorized with a client id and client secret, only then is the proper access token returned to the client. Think of it as 2 keys to get into 1 lock.
C
Community

From the OAuth 2.0 Spec:

The authorization code provides a few important security benefits such as the ability to authenticate the client, and the transmission of the access token directly to the client without passing it through the resource owner's user-agent, potentially exposing it to others, including the resource owner.

So, basically - the main reason is to limit the # of actors getting the access token.

"token" response is intended primarily for clients that live in the browser (e.g.: JavaScript client).


just for limiting the number of actors?? and protecting of exposition?? does the added complexity really makes sense?
That and client authentication. More background: tools.ietf.org/html/…
The code is a way of not having the app_secret written into your JS client. The client requests the code, sends the code to the API requesting the token. Stores the token locally and keeps your app_secret into the server side. Away from attackers. It is a one more step for security.
this doesn't answer the question of why would you use response_type: 'code token'
r
rofrol

If you look at the flow of Authorization Code OAuth type, yes, there are actuary two steps:

=> authorization_code => access_token, refresh_token

In step1: the user tells the OAuth Server that "I want to auth this client (client_id) to access my resource. Here is my authentication (user_session_id or what else)"

In step2: the client (client_id) tells the OAuth server that "I've got the user the authorization (authorization_code), please give me an access token for later access. And this is my authentication (client_id & client_secret)"

You see, if we omit step 2, then there is no guarantee for client authentication. Any client can invoke step1 with a different client_id and get an access token for that client_id instead of its own. That's why we need step2.

If you really want to combine step1 and step2, you can do something like this:

<client_id, redirect_uri, client_secret> => access_token, refresh_token

We use this approach in our Open API Platform, and we haven't find any security problem yet.

BTW, there is actually an Implicit Grant type, that is:

<client_id, redirect_uri> => access_token, refresh_token

It is generally applicable to client only application which have no server backend. In that case, the OAuth server must ensure that the redirect URI belongs to that client (same with the register redirect_uri, for example).


C
Community

The mix-up came because the user on behalf of himself and not the client app authenticate against the authorization server (i.e. facebook). Its much simple to secure the client app (with https) then the user-agent (browser).

Here is the original formulation from IETF-oauth (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-threatmodel-08#section-3.4):

3.4. Authorization Code

An authorization code represents the intermediate result of a successful end-user authorization process and is used by the client to obtain access and refresh token. Authorization codes are sent to the client's redirection URI instead of tokens for two purposes.

Browser-based flows expose protocol parameters to potential attackers via URI query parameters (HTTP referrer), the browser cache, or log file entries and could be replayed. In order to reduce this threat, short-lived authorization codes are passed instead of tokens and exchanged for tokens over a more secure direct connection between client and authorization server. It is much simpler to authenticate clients during the direct request between client and authorization server than in the context of the indirect authorization request. The latter would require digital signatures.


M
Michael R

Answer) You need/want both the code and token for extra security.

According to Nate Barbettini we want the extra step of exchanging the authentication code for the access token, because the authentication code can be used in the front channel (less secure), and the access token can be used in the back channel (more secure).

Thus, the security benefit is that the access token isn't exposed to the browser, and thus cannot be intercepted/grabbed from a browser. We trust the web server more, which communicates via back channels. The access token, which is secret, can then remain on the web server, and not be exposed to the browser (i.e. front channels).

For more information, watch this fantastic video:

OAuth 2.0 and OpenID Connect (in plain English) https://youtu.be/996OiexHze0?t=26m30s (Start 26 mins)


This is the only useful, on-topic answer.
I do not understand this part. client exchanges authorization code for an access token without revealing the token to resource owner user agent. Agreed. But how the user agent can request the resource without access token. anyhow user agent will know the access token right ?
Client and resource owner will have different token being maintained ? For e.g I have logged in with facebook in Stackoverflow. SO backend will get access token based on my consent and the communication between myself and SO will be in a different scheme / token
@SundarRajan, this is my understanding: the user agent requests the resource via its own backend, which acts as a proxy. This way, the user agent really doesn't have to know the access token. However, the application backend will have to authenticate the user agent before requesting a resource for it.
A
Amit Kumar Gupta

Theoretically,

Access Tokens cannot tell us if the user has authenticated but auth code does.

Auth code should not be used to gain access to an API but access token should be.

If you have a single page application or mobile application with no or minimum backend, your application may want to access user's FB data directly at frontend. Hence the access token is provided.

In another case, you may want a user to register/login to your app using some external auth service provider like Facebook, Google etc. In this case, your frontend will send the auth code to the backend that can be used to get access token from Facebook at serverside. Now your server becomes enabled to access user's FB data from the server.

https://i.stack.imgur.com/lrLe3.png


What is the source of the image?
C
Community

Basically, as an extension of Lix's answer, the access code route allows a Resource Owner (i.e. the Facebook User) to revoke authorization for their User Agent (i.e. their browser), e.g. by logging off, without revoking authorization for an offline Client (i.e. Your Application). If this is not important, then there is no need to use the access code route.

Furthermore, the access code is provided to ensure that the Token provided to a server is actually registered to the Resource Owner (i.e. the Facebook User), and not the User Agent (or a Man-in-the-Middle).

This seems similar to the question of either choosing the implicit vs authorization code grant flow. In fact, here is what looks like an opposite view point?!.

Also, as Drew mentioned,

When the access token expires, attempts to use it will fail, and a new access token must be obtained via a refresh token.

another piece is the refresh token, but I don't see that being explained too well in the FB Docs. If I'm correct, the implicit grant (the direct token) should be really short lived, but that is to-be-enforced and FB.js seems to hide a lot of that (this one I have not looked as deep into).

If I'm correct, the code%20token is an optimization allowing both the User Agent to have a token and allowing for the server to initiate the token exchange process in a single request (as anything over Network IO is considered expensive, especially to a User Agent).


J
Justin Ehrlich

It’s because the access token is given to an AUTHENTICATED client (third-party app) using a shared secret that only FB and the client knows. The only way that the user could directly request the access token is by knowing the shared secret, which would make the secret public and could lead to a man-in-the-middle attack. Further, while FB can guarantee a secure connection to the user, FB can’t guarantee the handoff of the token to the client is secure. However, FB (and OAuth2) does require a secure connection between the client and FB. The access token is tied to the client public ID (usually hashed), which means only the original client application can use it to request the token because the secret is sent along with the authorization code to get the access token.


A
Ashane.E

In OAuth 2.0 with facebook, the overall concept is simple as follows.

Step 1. Obtain "Authorization Code" by a GET request

request URI: https://www.facebook.com/dialog/oauth
Params:
    response_type=code
    client_id={add your "App id" got by registering app}
    redirect_uri={add redirect uri defined at the registration of app}
    scope={add the scope needed in your app}
Headers: None

Step 2. Obtain the "Access Token" by sending the authorization code as a POST request

    URI: https://graph.facebook.com/oauth/access_token
    Params:
        grant_type=authorization_code
        client_id=<add your "App id" got by registering app>
        redirect_uri=<add redirect uri defined at the registration of app>
        code=<obtained authorization code from previous step>
    Headers:
        Authorization:Basic encode <App Id:App Secret> with base64 
        Content-Type:application/json

Step 3. Use the access token got from above step and retrieve user resources


L
Lix

You recieve a token when the user logs in. But you might want to change the token when you are performing other actions. EG posting as your app/page or posting as a user with offline_access.


If you ask for the permissions you need on the first time, can't you use the same token? And if you have offline_access, then you can save the token. I'm still confused about why the code is required in the flow...
you can certainly use the same token - but the normal tokens expire after a while. TBH I have never used that "code" parameter manually - all my logins are done by retrieving the loginURL from the SDK's...
I think that is only on the php sdk for now. On the most recent oauth2 authentication docs, if you want to do anything other than php server side, you need to use "code"