What is preventing the following scenario:
Attacker downloads legitimate app that makes a legitimate OAuth 2.0 Authorization Grant to a desired resource
Attacker records the client_id and redirect_uri
Attacker creates phony app in the image of the real thing
Victim downloads phony app and begins OAuth 2 flow for desired resource
Phony app provides identical client_id and redirect_uri as legitimate app
Victim authenticates and authorizes use of desired resource
Phony app catches the redirect without ever hitting URL (I know iOS can do this) and securing its contained authorization code.
Phony app now has access to desired resource "in the name" of a legitimate app
Is there any way to actually validate the identity of an app making an authorization request when using a public client (no client_secret)?
There is no inclusive protection against that threat as the OAuth 2.0 security considerations spec acknowledges: https://www.rfc-editor.org/rfc/rfc6819#section-5.5. It acknowledges that the user plays an important role here. Some remarks though:
App installation control via Mobile Device Management may be applicable in some (enterprise) use cases to mitigate this.
Dynamic Client registration (http://openid.net/specs/openid-connect-registration-1_0.html) may be used to generate a per-instance client secret so that after registration the Client is a confidential Client. Yet the the app integrity question then still exists (only) in the initial bootstrapping/registration phase.
Related
I am developing a SPA application in angular and I have a lot of confusion about the correct way to implement authentication and authorization.
First of all, the application is a first-party app, which means that I am developing both the authorization server and resource servers.
The users that logs in the application must have full access to their resources on the platform.
So, I am doing it using OAuth2.0 and I have a couple of doubts about the domain of the protocol as well as security concerns.
First question:
The first question is if OAuth should be actually used to authorize first party applications. From my understanding this is a delegation protocol used to grant a third-party application controlled access to the user's resources on the platform, upon user consent. How does this fit in the context of a first-party app? In that case the app should get an access token with a scope that allows full access, right?
Second question:
Since this is a Single Page Application I couldn't store a secret on client side. So I am opting for using the authorization code grant with PKCE which would seem to be appropriate to manage this scenario. In this case I wouldn't ask for a refresh token but I would only retrieve the access token and using silent check to refresh it. I do not want to have refresh token insecurely stored on the browser. Is this PKCE really secure? The secret is generated dynamically but a attacker could eventually create a system using the same public client id and managing the PKCE properly, and finally get an access token that, in my case, gives full access to the users resources.
I could in the future allow controlled access to my app's resources to third party app, that's also one of the reason why I stick with OAuth.
The first question is if OAuth should be actually used to authorize first party applications. From my understanding this is a delegation protocol used to grant a third-party application controlled access to the user's resources on the platform, upon user consent. How does this fit in the context of a first-party app? In that case the app should get an access token with a scope that allows full access, right?
Yes, this makes sense to me. We skip the 'grant permissions' step for our own apps.
Is this PKCE really secure?
Yes, even without PKCE, authorization_code is pretty secure. Adding PKCE solves a a few potential security issues, but I would be somewhat inclined to call them edge cases. It is definitely right now the recommended choice.
The PKCE rfc has more information about the motivations behind PKCE:
https://www.rfc-editor.org/rfc/rfc7636#section-1
I actually came here looking for the answer to Question 1. My take is that in situations where we have no third party apps requiring access to our APIs we do not need OAuth. If we still need to use OAuth, then we can use Resource Owner Password Flow for first party apps. I have not seen any convincing answer anywhere confirming or rejecting this opinion but this is purely based on my understanding of OAuth.
Now, I am mainly writing this to answer Question 2. PKCE protocol is secure and attacker would not get token in this scenario. The reason is that the Authorization Server uses pre-registered "Redirect Uri" to send the token to. To be precise, the Auth Server would simply ask the browser to redirect user to "Redirect Uri appended with Access Token". Browsers do not allow javascript interception of Redirection requests. Therefore, an attacker would not be able to get hold of the token and the user will be redirected from attacker's site to yours at the end.
I am trying to choose the right authentication flow for an application:
Fontend is an Progressive Web App accessible only via HTTPS. It'is done in Angular, Single Page Application.
External Authorization Server
Backend accessible via REST calls
For now I am using Authorization Code Grant flow.
What have I tried:
I've checked official site. There is a list of possible flows (Authorization Code, Implicit, Password, Client Credentials, Device Code, ...),
but no clear indication how to choose between them.
Then I found this excellent article on Auth0.com. Unfortunately PWA + server side beckend is not present in their scheme.
Could you please tell me what OAuth2 flow is appropriate to my context and why?
Assumptions (the way I understood the question):
You own and develop both frontend (Angular app) and backend (server-side REST API).
You want to outsource authentication to a 3rd party identity provider.
You want the Angular app (Client) to hold the token and be able to authenticate on the backend (Resource Server), with the identity of your user (Resource Owner) established on the 3rd party (Authorisation Server / Identity Provider (IdP) ).
First, a sidetrack. For this use-case, OpenId Connect (OIDC) would be a better fit, because that supports the identity element. The point in OAuth2 is to authorize your app to do stuff on the 3rd party. What you want is establish the identity of your user, with the help of the 3rd party, and that's what OpenId Connect does.
Ok, so which flow (OIDC is still based on OAuth2).
The first questions are whether the Client is trusted to do anything on the Resource Server, and whether it can securely store a secret. This is clearly not the case, a client-side app is not trusted, and cannot hold a secret. In the client credentials flow, the client uses a secret to authenticate on the IdP to receive a token for the resource server. This would mean your Angular app stores a password which it uses to get a token for your backend, clearly not what you want.
Resource owner password credentials flow is used when the client is trusted to handle user credentials. In your use-case this is not good, because practically it would mean your Angular app would get the users password to forward it to the IdP in exchange for a token. Your Client should not have access to the user password, it is not trusted.
Now comes the more interesting part.
The question is whether your Client has a server-side to securely hold a secret. If it does, Authorization Code Grant is good, because it allows your user to authenticate on the IdP, get redirected back with an authorization code, and the server-side can then exchange that for an access token to be used on the resource server. However, your Client in this scenario does not have a server-side, as far as I can understand the API is the resource server. So this is not good for you, because it needs a client secret, and you can't store it in your Angular app.
And this pretty much leaves you with the Implicit Flow, for which you don't need a client secret, but on the other hand it's difficult to do things like refresh tokens. In the flowchart you linked to, the last question is whether your Client is an SPA - and in your case it is, so you should go for the implicit flow by default.
This is probably the most secure model for you, because even in case of a compromise of your Client, your user credentials are still safe (the Angular app never has access).
However, you can model this whole thing differently, and that simplifies it quite a bit.
As far as I could understand, you own both the Client and the Resource Server, and the Resource Owner is using the Client, you just want to offload authentication while you still manage users in a 3rd party service.
Looking at it this way, your Client is trusted to access user credentials, and the user using it is the Resource Owner. So you could use the Resource Owner Password Flow, where the user enters his credentials directly into the Angular app, which goes to the IdP, gets a token, and Angular simply uses that to access stuff on the API (Resource Server).
The risk compared to the Implicit Flow is that if the Angular app is compromised, user credentials will be disclosed to the attacker. Whether you want to accept this risk entirely depends on you. Note that this would obviously not work if the IdP is a well-known service (like a social website for example), because as your user I wouldn't want to give my social site password to your app. But as long as you manage users anyway, it can be acceptable to trust the Client.
While the previous anwser was perfectly accepted in 2018, it should be considerate as a security risk nowaday.
IETF source concerning implicit flow.
The correct flow to used now for a PWA and in general any public, browser based client that can not rely on client_secret is the authorization code flow + PKCE
I'd like to develop a native application (for a mobile phone) that uses OAuth 2.0 Authorization to access protected resources from a resource API. As defined in section 2.1 the type of my client is public.
Upon registration, the Authorization Server provides a client_id for public identification and a redirect_uri.
The client will make use of Authorization Code to receive it's Authorization Grant from the Authorization Server. This all seems secure (if implemented correctly) against any attacker in the middle.
In section 10.2 client impersonation is discussed. In my case, the resource owner grants the client authorization by providing it's credentials via the user agent to the Authorization Server. This section discusses that the Authorization Server:
SHOULD utilize other means to protect resource owners from such
potentially malicious clients. For example, the authorization server
can engage the resource owner to assist in identifying the client and
its origin.
My main concern is that it's easy to impersonate my client once the client_id and redirect_uri is retrieved.
Due to the nature of a public client, this can either be easily reverse engineered. Or in my case, the project will be open source, so this information can be retrieved from the web.
As far as I've understood from section 10.2, it's the resource owner's responsibility to check that the client is legitimate by comparing with what the Authorization Server SHOULD assist with.
In my experience with third party applications requesting an Authorization Grant from me, all I get is a page with some information about the client that actually should be requesting that grant. Based on pure logical sense, I can only judge if the client that's requesting the grant is actually the client that the Authorization Server is telling me who it should be.
So whenever we are dealing with PEBKAC (which I think occurs frequently), isn't it true that impersonators can easily access protected resources if the resource owner just grants them (which might identically look like my legitimate client) authorization?
TLDR - You want oauth access tokens to be issued only to valid clients - in this case devices that installed your app, yes?
First - Oauth2 has multiple workflows for issuing tokens. When YOU are running the Oauth2 service and its issuing tokens to devices running YOUR app, authorization code / redirect URL is not the relevant workflow. I suggest you read my answer here - https://stackoverflow.com/a/17670574/116524 .
Second - No luck here. Just run your services entirely on HTTPS. There is no real way to know whether the client registration request is coming from an app installed from the official app store. You can store bake some secret into the app, but it can be found via reverse engineering. The only possible way this could possibly happen can be some sort of authentication information being provided by the app store itself, which does not exist yet.
Since OAuth 2.0 Implicit Grant Flow exposes its mechanism e.g. using JavaScript, in the client app to the resource owner, the client Id and the access token are exposed. I have not been able to find a clear answer on what can be done to prevent from exploiting the exposure.
What are some measures to prevent problems with the following scenario? If it's apparent that I am not understanding the flow correctly, please do point out.
Scenario
Client A - a legit client who has been granted its own unique client Id from the authorization server.
Client B - a client the authorization server is not aware of, copies the client Id of Client A, draws in innocent resource owners and uses their access tokens to gain access to their private information.
These are some options I can think of to fix the issue.
Create an IP white list and map to each known client. Check against the authorization server when authorizing and calling the resource server.
Set throttling on the end points of the resource server to detect abnormal activities.
Well, this is the reason why the OAuth specification (RFC 6749) warns against about security weaknesses of the implicit flow in Section 10.6. It's not clear that the counter-measures you describe would be effective in a general setting on the internet. For example, IP headers are insecure and can be easily spoofed. I would only use the implicit flow for the applications that require the lowest level of security (e.g., read-only display of information).
The token is secured using SSL between the client and the server. Therefore the content is encrypted but the URI is not. You can put store the token in the html body because it is secure with the exception of browser add ons. Don't use third party content servers to host JavaScripts, if they are compromised their scripts can read your html. The user can see the token and copy it to their own app if they want but its protecting their resources so... Ultimately I like Implicit flow because of its simplicity.
Ultimately the servers handling of the token can be a problem out of your control. Chose a server that does not include the token in the URI, its not safe. Similarly your shouldn't post back to the server sensitive information in the URL.
If you find a library that guarantees security, please post it.
From the OAuth 2.0 Threat Model and Security Considerations draft:
4.4.1.13. Threat: Code substitution (OAuth Login)
An attacker could attempt to login to an application or web site
using a victim's identity. Applications relying on identity data
provided by an OAuth protected service API to login users are
vulnerable to this threat. This pattern can be found in so-called
"social login" scenarios.
As a pre-requisite, a resource server offers an API to obtain
personal information about a user which could be interpreted as
having obtained a user identity. In this sense the client is
treating the resource server API as an "identity" API. A client
utilizes OAuth to obtain an access token for the identity API. It
then queries the identity API for an identifier and uses it to look
up its internal user account data (login). The client asssumes that
because it was able to obtain information about the user, that the
user has been authenticated.
If the client uses the grant type "code", the attacker needs to
gather a valid authorization code of the respective victim from the
same identity provider used by the target client application. The
attacker tricks the victim into login into a malicious app (which may
appear to be legitimate to the Identity Provider) using the same
identity provider as the target application. This results in the
Identity Provider's authorization server issuing an authorization
code for the respective identity API. The malicious app then sends
this code to the attacker, which in turn triggers a login process
within the target application. The attacker now manipulates the
authorization response and substitutes their code (bound to their
identity) for the victim's code. This code is then exchanged by the
client for an access token, which in turn is accepted by the identity
API since the audience, with respect to the resource server, is
correct. But since the identifier returned by the identity API is
determined by the identity in the access token (issued based on the
victim's code), the attacker is logged into the target application
under the victim's identity.
Impact: the attacker gains access to an application and user-specific
data within the application.
Countermeasures:
All clients must indicate their client id with every request to
exchange an authorization code for an access token. The
authorization server must validate whether the particular
authorization code has been issued to the particular client. If
possible, the client shall be authenticated beforehand.
Clients should use appropriate protocol, such as OpenID (cf.
[openid]) or SAML (cf. [OASIS.sstc-saml-bindings-1.1]) to
implement user login. Both support audience restrictions on
clients.
This is rather confusing to me: «the attacker needs to gather a valid authorization code of the respective victim from the same identity provider used by the target client application». What's "the respective victim" and what does "identity provider" mean in this and subsequent uses?
The whole attack description is obscure. I came to understand it as "one shouldn't use OAuth 2.0 to implement user login", but wouldn't that mean that major platforms such as Facebook are vulnerable? And vulnerable to what, exactly?
I probably only need a clarification of some of the terms used in this paragraph.
I found the answer by myself. The wording in this section is a bit confusing, but the attack is quite simple. "Identity provider" is the name for the resource server used to verify the identity of an user.
Basically it's a case of using an authentication code issued for a client application to obtain an access token by a different application. I try to outline the steps in a clearer way.
Attacker registers a malicious client (e.g. an app registered to Facebook).
Victim user is tricked into logging into the malicious client using a "Login with third party" button (e.g. "Login into Facebook") triggering OAuth 2.0 authorization_code flow.
The malicious client gets the authorization_code.
The attacker uses the just obtained authorization_code with another app and obtains access to that app as the victim user.
Step 4 is only possible if authorization_codes aren't bound to a specific client. Auth codes issued to a client can only be used by that same client to obtain an access token.
Of course Facebook is not vulnerable, as this requires only a basic check from the authorization server to defeat.