I am using OkHttp to login to a website with username and password. After login any attempt to request a resource is followed with a token=xxxxxxaxx-xxax-xxxa-xxaa-axaxxaxaxxxx in the query path.
I am not certain this is a security token, or just a UUID? It follows the format 8-4-4-4-12 in length and is always lower case alphanumeric.
In order to send new requests to the service I need to acquire/generate token after login. In some cases I note in future requests that both the InstanceId=&token= is passed - where they both pass the same value for token and instanceid.
After login I do not see this token in the of the response headers, it just starts to appear in all future requests.
After login the following URLs are accessed:
portal
launch
htmlnavigator
getCSRFTokenVaue
getUserLocale
createToken
I have confirmed that the token returned by the createToken URL is not the same token that is used in later requests.
The various cookies sent by the server I can user with CookieManager, but where does the security token come from (or usually come from?) - What browser tools might help me beyond reading all the headers and responses.
It is a REST service, and each frame within the browser gets its own token, so difference requests in the same frame use the same token, open a new frame and that frame uses a new token.
The token is passed in the URI.
The web application UI has frames/pages within the main page and opening each new page generates a new token specific to that page
Multiple requests to each frame all send the same token so the tokens are not query authentication (like here)
If more information is required I will update the question but I can not name the system.
It may not be possible to know exactly what the url token is used for, but from what you say, different frames (tabs) in the same browser get different tokens, so it could be a frame specific session id (unusual but might be used to permit multiple sessions in systems where auth is stateless while preventing side-channel attacks) or more likely a form of double-submit CSRF token.
I am currently using a client-side React component to have a user login to Facebook via OAuth in my application. On the server-side, I use the npm package passport-facebook-token to validate the authenticity of the accessToken after a successful client-side login.
One practice I do not see often is in addition to asking Facebook if the accessToken is valid, shouldn't the server also check if the email provided by the client's payload matches the e-mail coming back from Facebook? Allow me to use defined client/server technologies to illustrate my question:
1) User uses React component on the client to authenticate with Facebook.
2) React component successfully authenticates with Facebook and fires an HTTP request to the server with an access token and the user's email.
3) The server, running Node.JS and passport-facebook, now needs to verify the authenticity of the access token directly from Facebook. Facebook does not care for an e-mail. It will just verify the access token.
4) Facebook returns a response to Node.js confirming the authenticity of the access token. The response also contains other metadata about the user, including their email and other profile data.
My question is, should Node.js take the email that's also coming back from Facebook's access token verification payload, and verify that it is what came back from the React client? Would this not prevent someone from brute-forcing an accessToken and require them to not only have an accessToken but also know who the accessToken belongs to? This could prevent a user from submitting a bunch of HTTP POST requests to the Node.js server attempting different access tokens. They would not only have to guess an access token assigned to the application's clientID, but also know the e-mail it belongs to. Is this an over-engineered approach?
Really the best way I can think of to make your OAuth accessToken and 'code' value less prone to brute-forcing is using a Cryptographic Number Generator to create a 128-bit length string of random data and encoding it with base 64 to use as your code. It's extremely unlikely that it would be guessed by a computer or by someone redirecting to and from the authorization endpoint and the redirect-uri with query parameters.
Another method of fortification is limiting the rate of authorizations by IP address (which you can do instead of email through Node.js) but that is usually not a problem for most well-equipped hackers. I highly advise the first method for creating a more secure service.
Your approach to validate the email as well as the token is a bit superfluous because Facebook's opaque user access tokens are inherently tied to email.
From Facebook
An access token is an opaque string that identifies a user, app, or Page
"opaque" is defined by Auth0 here
Opaque Access Tokens are tokens in a proprietary format that typically contain some identifier to information in a server’s persistent storage
In your case, the identifier is the user's email, and the server belongs to Facebook.
I will elaborate further. Here is your step by step with some edits:
User uses React component on the client to authenticate with Facebook, inputting both their email and password directly to Facebook. React component gets the token from Facebook on login success.
React component successfully authenticates with Facebook and fires an HTTP request to the server with an access token and the user's email.
The server, running Node.JS and passport-facebook, now needs to verify the authenticity of the access token directly from Facebook. Facebook does not care for an e-mail. It will just verify the access token because the access token is already tied to the email.
Facebook returns a response to Node.js confirming the authenticity of the access token. The response also contains other metadata about the user, including their email and other profile data.
This is Facebook's bug bounty program. If their OAuth was really as cracked as to require a second email validation, it would have been patched almost immediately by this incentive.
I am trying to setup OpenID Connect Authentication (Single-tenanted) for my web application. I understand how Reply Url in AAD is supposed to work. AAD admin registers a web application with SignInUrl, ReplyUri, AppIdUri,.. Microsoft AAD handles the complete user experience to prompt & validate the credentials. An attacker may not be able to pose legitimate site attack (since it is *.microsoftonline.com page).
Questions:
What is the real purpose of Redirect_Uri in OpenIdConnect? Does it fight Redirect_Uri Attack?
I tried to send different Redirect_Uri from web client. Microsoft AAD fails by reply urls do not match error. But while refreshing the web application, it is signed in now. Should AAD not invalidate my attempt of logging in with illegitimate redirect uri?
Please suggest me how to view Redirect Uri. I would like to harness the real benefit.
What is the real purpose of Redirect_Uri in OpenIdConnect?
From the OpenID Connect, 3.1.2.1 Authentication Request:
redirect_uri
REQUIRED. Redirection URI to which the response will be sent.
This URI MUST exactly match one of the Redirection URI values
for the Client pre-registered at the OpenID Provider [...]
So, the purpose of redirect_uri is to tell the OpenID Provider (Azure AD, in your case) where the response to the request should be sent, after the user signs in.
Does it fight Redirect_Uri Attack?
The parameter itself offer the functionality described above, it doesn't mitigate any attack. It is the responsibility of the client (i.e. your app) and the OpenID Provider (i.e. Azure AD) to ensure they are doing the right thing to prevent exposing the risk of an attack (including an attack related to redirections).
For example, if an OpenID Provider did not validate that the redirect_uri from the request exactly matches a redirection URI configured for the client, then an attacker might be able to construct an authorization request with a redirect_uri pointing to a URL controlled by the attacker, and then trick a user into triggering the request. The response to the request would then be sent to the attacker, rather than to the relying party the user thinks they're signing in to.
There are other attacks related to redirect_uri which could happen if the relying party (i.e. your app, in this case) exposed a vulnerability (for example, by enabling an open redirection attack, or by authorizing a reply URL which is not actually in your control).
Many of these (and other) attacks, as well as the current best practices to mitigate or prevent them, are described in OAuth 2.0 Security Best Current Practice.
I tried to send different Redirect_Uri from web client. Microsoft AAD fails by reply urls do not match error. But while refreshing the web application, it is signed in now. Should AAD not invalidate my attempt of logging in with illegitimate redirect uri?
This seems like there is an issue in your application. When Azure AD detects that the requested redirect_uri does not exactly match an authorized reply URI for the client, Azure AD does not redirect back to the client with an authorization code or any tokens.
It is possible that your app had already established a session previously, or is incorrectly processing the OpenID Connect flow. It's impossible to say without knowing the specific details of how the app is implemented.
Now I think I found the mystery behind the signin-redirect_uri anomalies.
Questions:
What is the real purpose of Redirect_Uri in OpenIdConnect? Does it fight Redirect_Uri Attack?
[OP] Yes, it does. If redirect_uri domain differs from AAD server Registration and web client, it invalidates the sign-in attempt.
I tried to send different Redirect_Uri from web client. Microsoft AAD fails by reply urls do not match error. But while refreshing the web application, it is signed in now. Should AAD not invalidate my attempt of logging in with illegitimate redirect uri?
[OP] Redirect_Uri does not behave when I hosted my application in localhost even on different ports or same domain. So, it ignores Redirect_Uri validation, if I click on Sign-In despite the first Reply-Uri-Mismatch error.
Please note that Redirect_Uri does handle Open redirect attack if an attacker wants to redirect the victim to illegitimate page for re-entering the credentials.
We would like to implement "Sign-in with LinkedIn" in our app. Since the app has JS fronted and RESt-based backend, we decided to exchange JSAPI tokens for REST API OAuth tokens as described here.
If a user successfully signs in, the frontend sends credentials cookie with client-side bearer token and member ID to the backend. On the backend we check if a user with such a member ID already exists and if not, we exchange JSAPI token for REST API OAuth token, retrieve user details from LinkedIn a store it in our database.
Now the question is if we can use that cookie to authenticate each user's request to our REST backend. After a user successfully signed in via JSAPI, the cookie should be automatically passed to our backend on all subsequent requests so we can check member ID. Are there any drawbacks that we missed? Or is this idea as a whole wrong?
Should we rather authenticate a user only once by means of the cookie and then issue our own authentication token and send it back to the client?
The way cookies work in general is they are passed on every request to the domain they belong to. LinkedIn is setting a credentials cookie to your domain.
As long as you are validating those credentials on every request it's perfectly acceptable to use their tokens as authentication.
Personally I don't find that to be a great idea and would prefer to validate their credentials once and create my own auth token to use from there on out. You can always set that token to expire at some-point and re-validate the LinkedIn credentials (which will still be getting sent on every request anyway). This limits the amount of times you're checking with LinkedIn and should increase the responsiveness of your app.
Either way could work.
If you are using the LinkedIn cookie to validate a user by member id, you should validate the cookie's signature on each request per section 2 of the doc you linked and question 2 of the FAQ.
Using your own token could make it easier to implement an account which belongs to your app and is not necessarily connected to LinkedIn, assuming there's the potential to either connect solely with some other service(s) or no 3rd part(y/ies). Still should validate any time you trust the member id in the cookie though.
The doc provides a validation example in PHP, and if you're interested in improving a ruby version, I have a shameless plug.
The flow that you've outlined in your latest comment of going straight for the OAuth tokens is the best way to go if you were only signing in to convert the JSAPI tokens to OAuth tokens and then not using the JSAPI further. If you were planning to actually use both the JSAPI tokens within your front-end app and the OAuth tokens on your back-end, then it's better to take the conversion route.
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.
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.
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.
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).
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)
If you look at the flow of Authorization Code OAuth type, yes, there are actuary two steps:
<user_session_id, client_id> => authorization_code
<client_id, redirect_uri, authorization_code, client_secret> => 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).
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.
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.
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).
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
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.
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.