In the Google developer console, when you create new app credentials for use in OAuth 2.0, and you specify a web app, it requests that you register callback URI and JavaScript origins.
I don't have a precise understanding of the need to register these.
For the callback URI, presumably this prevents a 3rd party who presents a malicious page to a user from getting the authorization code. However, the client id and secret are still hidden in the app server, so isn't the malicious application unable to do anything anyway?
Furthermore, if the callback URI is already registered, what does registering the JS origins separately accomplish. Unlike the callback URI registration, this is not mentioned by the OAuth 2.0 spec, it's something Google chose to implement.
Thank you for your help!
When you request a token, that token will be passed to the callback URL. By only permitting callback URLs that you have configured in the API console, you are preventing malicious users from spoofing the request and having the token sent to a third party. I suspect the aspect of OAuth that you've missed is that the callback is sent via a browser redirect, so is easy to fake.
Callback URLs are part of the OAuth server flow.
JS Origins come into play when you are using the client (Javascript) OAuth flow. They ensure that any OAuth request has come from a page that originated on your site.
The server flow is ...
OK I think I understand a bit more from reading the spec. https://www.rfc-editor.org/rfc/rfc6749#section-10.6
It is to prevent an attack by a user of the same client An attacker can create an account at the same client and initiate auth flow, but he replaces the redirect URI with his own URI.
He then tricks a victim into following the link to authorize the same legit client they are using. However, the auth code is now sent to the attacker URI.
The attacker then completes the flow by providing the auth code back to the client, which the client uses to complete the flow obtaining the token. However, this token may be associated by the client with the attacker, allowing him to impersonate the victim.
Related
I am building an Angular SPA app and using Okta as an Idp. since its an SPA so I think I need to use Implicit flow. I have two queries here-
Since in Implicit flow a refresh token is not issued, does it means that th user will be logged out of the app after the token expires and he has to log in again?
Why do I need to use Implicit flow in case of SPA? why not Authorization code flow? since I have control over both the front end (SPA) and back end (REST API) . for example in case of Spring MVC architecture for the web app Authorization code flow is possible.
Thanks,
pchh
Yes, if the token expired, you have to re-autenticate. Normally you still have a valid session on the identity providers site, so you can do a "silent" login using an iframe. Libraries like oidc-client support a silent login, which can do this for you.
You need to use implicit (or hybrid) flow, when you need to access to the access token from your javascript app. With authorization code flow your javascript app doesn't get the access token, so if your API needs an access token for authorization, what are you going to send?
If your auth server supports OpenID Connect (OAuth2 extension) and single sign-on (SSO) feature, to get a new token before the old gets expired, use an iframe with a URL you used for authentication, but add prompt=none parameter (and possibly id_token_hint parameter). See OpenId Connect RFC. The prompt=none parameter tells the /auth endpoint to issue a new token(s) if the user has an open SSO session at your OAuth2 server. If not, the request will fail. There is a separate RFC for session management.
The Authorization code flow requires you to access the /token endpoint, which usually requires authentication (client ID + client secret) and you cannot keep the secret safe in a browser. For this reason, the token endpoint doesn't use to support CORS headers, so you cannot access it using XHR. Using the Auth code flow, you get a code as a redirect URL param (?code=), which gets to the server hosting your SPA (browser sends it there after redirect). The implicit flow returns tokens in hash part of the redirect URL (#access_token=), which stays in a browser (it's not sent to the server), so it's safer.
I'm building a web app that uses the Oauth2.0 protocol. I have registered my app with the authorization server and received my client id and client secret.
I'm now working on Authorization part and specifically using the Authorization Code grant type. In that process i'm sending the user to the authorize endpoint with the following query parameters:code, client_id, redirect_uri, scope and state. (omitting the client_secret)
The problem that i'm dealing with is i'm getting an error back saying I need to provide the client_secret as well.
I was under the impression the client_secret is not needed at this part and shouldn't be sent in this request but rather when the client sends the authorization code (along with id & secret) to obtain the access token.
So my question is, Is it wrong (against oauth 2 protocol) that the authorization server requires the client secret to be sent in the request for the authorization code?
I am not 100% sure of this, but I did some research myself and what I found is that is not a real problem not to keep the "client secret" a secret. The only possibility of someone malicious being able to get through the Authorization specs is prevented by some facts:
1. Client need to get authorization code directly from the user, not from the service
Even if user indicates the service that he/she trusts the client, the
client cannot get authorization code from the service just by showing
client id and client secret. Instead, the client has to get the
authorization code directly from the user. (This is usually done by
URL redirection, which I will talk about later.) So, for the malicious
client, it is not enough to know client id/secret trusted by the user.
It has to somehow involve or spoof user to give it the authorization
code, which should be harder than just knowing client id/secret.
2. Redirect URL is registered with client id/secret
Let’s assume that the malicious client somehow managed to involve the
user and make her/him click "Authorize this app" button on the service
page. This will trigger the URL redirect response from the service to
user’s browser with the authorization code with it. Then the
authorization code will be sent from user’s browser to the redirect
URL, and the client is supposed to be listening at the redirect URL to
receive the authorization code. (The redirect URL can be localhost
too, and I figured that this is a typical way that a “public client”
receives authorization code.) Since this redirect URL is registered at
the service with the client id/secret, the malicious client does not
have a way to control where the authorization code is given to. This
means the malicious client with your client id/secret has another
obstacle to obtain the user’s authorization code.
// copy paste of hideaki answer
Concluding
OAuth2 specify that you need to inform your secret into a request if your application is a server-side based app (different than a single-page application or mobile) which does not make its source code available. However, if you can't control your base code, like in an native mobile application, you should look for another solution.
References
OAuth2 Documentation
Bear similar stack question
Simplifying OAuth2
I am writing some code to get Twitter and Instagram feed. Before I can write any code, I keep wanting to get a good understanding of oAuth because I have this nagging feeling that it is not all that secure and that most times, for instance when accessing public tweets, it is an unnecessary hassel. I started reading the oAuth 2 specification to get a better understanding, I am still in the middle of it. And I have a host of questions.
Let's use Twitter as an example.
A user accesses your site. You redirect them to Twitter for authentication and to obtain the authorization_grant code.
I understand this part is secure because the user authentication and the redirect to your website will happen over ssl. Is it enough for Twitter to support SSL or does your site also have to support SSL for the redirect to be secure? You wouldn't want the authorization code to be transferred insecurely, right?
Now that you have your authorization_grant code, your site will send a request to Twitter to obtain an access token. When making this request your site will send the authorization_grant code, your client id and client secret. Again I guess the communication is secure because this will happen over ssl. But what if the site has included the client id and secret somewhere in its HTML or Javascript, especially if it is a static site with no server side code?
Should the redirect url always be handled by server side code and the server side code should make the request for access token without ever going through HTML or Javascript?
Once you have the access token, you will include it in your request to obtain the user's tweets, to post tweets on their behalf etc. Again if the site in question were to include the access token inside its HTML or JavaScript along with the client id and secret, that would be pretty insecure, right?
It seems all the security of oAuth stems from ssl and the client's ability to keep their client secret secret. Am I right in this conclusion?
Another thing - in the first step of the process, when the client redirects the user to Twitter to authenticate and obtain the authorization_grant code, they could send in their client id and secret and get the access token directly instead of making a second request for it. I think this is what they mean by the implicit method in the specification.
So, why was this extra step of sending a second request to obtain access token added in the specification? Does it increase security?
I am not sure about twitter API, I am talking with respect to stackexchange API
https://api.stackexchange.com/docs/authentication
Again I guess the communication is secure because this will happen
over ssl. But what if the site has included the client id and secret
somewhere in its HTML or Javascript, especially if it is a static site
with no server side code?
client_secret is send only in the case of explicit flow. Explicit flow should be used by server side application and care should be taken to keep the client_secret safe.
So, why was this extra step of sending a second request to obtain
access token added in the specification?
Well, Implicit flow is less secure than explicit flow since access toke is send to the user agent. But there is an attribute expire in the case of implicit flow which will get expired unless you have specified scope as no_expiry. Also server side flow can be used only by the apps that are registerd
It seems all the security of oAuth stems from ssl and the client's
ability to keep their client secret secret. Am I right in this
conclusion?
Again client_secret will be available in server side flow. But yes, client should take care that access_token is not given out
Check out this link. It gives an example of possible vulnerability in ouath.
Using oAuth 2.0, in "authorization-code" Authorization Grant, I first call to "/authorize", get the code, and then use this code within a call to "/token" to get the access-token.
My question: why this is the flow? I guess it is from a security reason, but I cannot figure it out. Why the implementation is this way, and not getting the access-token immediately after the first call ("/authorize")?
Why do we need this code for?
Could it also be that by having this intermediate step prevents the client from seeing the access token?
From O'Reilly book:
Authorization code This grant type is most appropriate for server-side web applications. After the resource owner has
authorized access to their data, they are redirected back to the web
application with an authorization code as a query parameter in the
URL. This code must be exchanged for an access token by the client
application. This exchange is done server-to-server and requires
both the client_id and client_secret, preventing even the resource
owner from obtaining the access token. This grant type also allows for
long-lived access to an API by using refresh tokens.
Implicit grant for browser-based client-side applications The implicit grant is the most simplistic of all flows, and is optimized
for client-side web applications running in a browser. The resource
owner grants access to the application, and a new access token is
immediately minted and passed back to the application using a #hash
fragment in the URL. The application can immediately extract the
access token from the hash fragment (using JavaScript) and make API
requests. This grant type does not require the intermediary
“authorization code,” but it also doesn’t make available refresh
tokens for long-lived access.
UPDATE - yes indeed:
When Should the Authorization Code Flow Be Used? The Authorization
Code flow should be used when
Long-lived access is required.
The OAuth client is a web application server.
Accountability for API calls is very important and the OAuth token shouldn’t be leaked to the browser, where the user may have access to
it.
More:
Perhaps most importantly—because the access token is never sent
through the browser— there is less risk that the access token will be
leaked to malicious code through browser history, referer headers,
JavaScript, and the like.
The authorization code flow is meant for scenarios where 3 parties are involved.
These parties are:
Client
The user with his web browser. He wants to use your application.
Provider
Has information about the user. If somebody wants to access this data, the user has to agree first.
Your (web) application
Wants to access information about the user from the provider.
Now your app says to the user (redirecting his browser to the /authorize endpoint):
Hey user, here is my client id. Please talk to the provider and grant him to talk to me directly.
So the user talks to the provider (requests the authorization code and returns it to your app by opening your callback URL in his browser):
Hey provider, I want to use this app, so they require to access my data. Give me some code and I give this code to the application.
Now your app has the authorization code which is already known by client AND the provider. By handing this over to the provider your app can now prove, that it was allowed by the client to access his data. The provider now issues your (web) app an access token, so your (web) app won't have to redo these steps each time (at least for a while).
In case of other application types where your app is running directly at the client side (such as iPhone/Android apps or Javascript clients), the intermediate step is redundant.
Data on client side is generally considered unsafe. In the case of implicit calls where token is granted in the initial step itself, anyone with the access_token can request for data, the API doesn't know who is calling that API.
But, in the case of web-server apps where the application wants to identify itself, client_id with client_secret is sent along with authorization_code to get access_token, which in future can be sent independently.
Suppose, if access_token is granted initially itself then as client_id and access_token will still be considered exposed, so the app will have to send client_secret in addition to access_token every time to assure that request is really coming from it.
While in the current scenario, after getting access_token, further requests can be made independently without needing client_secret.
One important point is
Perhaps most importantly—because the access token is never sent through the browser— there is less risk that the access token will be leaked to malicious code through browser history, referer headers, JavaScript, and the like.
I think it is like this;
When we use the authorization code, we have 2 verification parts;
1; to verify ownership of the user, because he logs in
2; we know that the client, is really who he says he is because the client is sending his client_secret.
So if we would return the access token on the moment when the user authenticates instead of the authorization code, we know that it is the user requesting it but we dont know that it will be used for the registered client. So for example your webapp.
When we use the 'implicit grant'; (or return the access token instead of authorization code)
1; We know it is the user who is receiving the access token, but there is no need in getting a authorization code because the 'user-agent' based application is not checkable. It is checkable, if you think about it but it is usable for everyone. The client_secret is publicly viewable in the source code of the 'user-agent' based application so everyone can just 'view source code' and copy the client_secret and use this method to verify ownership of the client.
#ksht's answer is basically correct. For those looking for the simple,brief answer it is this:
Because the client app, (browser or native app), can have the delivered token intercepted. The oauth implicit flow does allow this but only under very specific circumstances. In all other cases either the browser can leak info (hacks in the OS, browser bugs , plugins) or for native apps your custom url scheme that maps the redirect url to the app can be intercepted. So the workaround is send back a code instead of a token (over tls) and use PKCE to ensure that the code can be securely exchanged for a token.
Hello
My scenario is the following.
Client Application (on mobile phone) connects to Facebook via normal authentication process.
User gives consent to the application to access profile, gets back authorization code for the user.
With that code, plus application id and secret, the client gets an access token to access the information.
Can the authorization code be passed to a web service, which in turn does a call to Facebook to obtain an access token the same way?
I am not sure that is possible because reading documentation it looks like the access token API requires a redirect uri as a parameter.
Here instead, there would be a web service call waiting to complete.
Hope this is not confusing... :)
thanks in advance
"I am not sure that is possible because reading documentation it looks
like the access token API requires a redirect uri as a parameter."
The spec says
redirect_uri (of the access-token request):
REQUIRED, if the "redirect_uri" parameter was included in the
authorization request ... their values MUST be identical.
technically, the client can pass the server the authorization-code and the "redirect-uri", so the server makes the call with the same redirect-uri as the client, and if you control both ends it might work. However, the tricky part is that the client must also send the server the client-id and the client-secret. And if that happens, it contradicts all the idea of oAuth2.