I'm currently working on oauth2 implementation and i wonder about CSRF attack.
I so very good explanation : in this scheme https://image.slidesharecdn.com/owasp-nulloauth2-160803124628/95/oauth-20-security-considerations-11-638.jpg?cb=1470228518 or this video https://www.youtube.com/watch?v=_xrhWLqX1j0 but i dont understand the goal.
At the end my account will have access to the attacker account, i cant get data from it but not the reverse. Am I right ? What is the benefit for the attacker to do this ?
Thank's for your answer,
There are several other answers (ex:- this and this) explaining the background of state and how it avoid csrf.
Best thing is to refer what is given by specification creators. RFC6810 - OAuth 2.0 Threat Model and Security Considerations contains many threats and counter measurements for OAuth 2.0. In that Threat: CSRF Attack against redirect-uri gives a solid overview on the threat. Following is an extract,
An attacker could authorize an authorization "code" to
their own protected resources on an authorization server. He then
aborts the redirect flow back to the client on his device and tricks
the victim into executing the redirect back to the client. The
client receives the redirect, fetches the token(s) from the
authorization server, and associates the victim's client session with
the resources accessible using the token.
Now client has tokens which belongs to attacker. No, attacker won't be able to access anything that belongs to client in resource server. But if client perform a storing operation (ex :- Document create), this will be sent to malicious party. Now malicious party get access rights to those freshly created resource. This is highlighted as below,
The
effective impact depends on the type of resource accessed. For
example, the user may upload private items to an attacker's
resources. Or, when using OAuth in 3rd-party login scenarios, the
user may associate his client account with the attacker's identity at
the external Identity Provider. In this way, the attacker could
easily access the victim's data at the client by logging in from
another device with his credentials at the external Identity
Provider.
So basically threat is associated with fresh data created at resource server.
Related
I'm considering a microservice architecture and I'm struggle with authorization and authentication. I found a lot of resources about oauth2 and openid connect that claim they solve the issue but it is not clear enough for me.
Let's consider we have a following architecture:
In my system I want to add a feature only for a certain group of users defined by role. I want to also know the name of the user, their email and id.
After my research I find the following solution to be a good start:
SPA application displays login form.
User fills in the form and sends POST request to authN&authZ server.
The server replies with access token (being a JWT) that contains name, email, id and role of the user. The response contains a refresh token as well.
SPA application stores the token and attaches it to every request it makes.
Microservice 1 and Microservice 2 check if the token is valid. If so, they check if the role is correct. If so, they take user info and process the request.
How far away from the good solution I am? The login flow looks like Implicit flow with form post described here but with implicit consents and I'm not sure if it's fine.
Moving forward, I find passing user data in JWT (such as name, email) to be not a good solution as it exposes sensitive data. I found resources that say it is recommended to expose only a reference to a user in token (such as ID) and replace such token with a classic access_token in reverser-proxy/api gateway when sending a request to a microservice. Considering such solution I think that following scenario is a good start:
SPA application displays login form.
User fills in the form and sends POST request to authN&authZ server.
The server replies with access token and refresh token. API gateway (in middle) replaces access token with ID token and stores claims from access token within its cache.
SPA application stores the token and attaches it to every request it makes.
Handling a request, API Gateway takes ID Token and based on the user ID generates a new access token. The access token is send to microservice 1 or microservice 2 that validate it as previous.
How do you find such solutions? Is this a secure approach? What should I improve proposed flow?
Thanks in advance!
You are on the right tracks:
ZERO TRUST
This is an emerging trend, where each microservice validates a JWT using a library - see this article. JWT validation is fast and designed to scale.
CONFIDENTIAL TOKENS FOR CLIENTS
Internet clients should not be able to read claims that APIs use. The swapping tokens in a gateway concept is correct, but the usual approach is to issue opaque access tokens here, rather than using ID tokens. At Curity we call this the Phantom Token Approach.
SECURE COOKIES IN THE BROWSER
One area to be careful about is using tokens in the browser. These days SameSite=strict HTTP Only cookies are preferred. This requires a more complex flow though. See the SPA Best Practices for some recommendations on security.
SPAs should use the code flow by the way - aim to avoid the implicit flow, since it can leak tokens in the browser history or web server logs.
SUMMARY
All of the above are general security design patterns to aim for, regardless of your Authorization Server, though of course it is common to get there one step at a time.
Don't use your own login form. As Garry Archer wrote, use the auth code flow with PKCE which is the recomended flow for applications running in a browser.
If you don't want to get an ID token, don't ask for the openid scope in the initial auth request. The type of issued access tokens (JWT or opaque) can often be configured on your OAuth2 server. So I see no need to issue new tokens at your gateway. Having more token issuers opens more ways of attacking your system.
Your backend modules can use the userinfo endpoint, which will give them info about the user and validate the token. This way, if the token was invalidated (e.g. user logged out), the request processing will not proceed. If you validate just a JWT signature, you will not know about the token being invalidated.
If you plan to make requests between your backend modules as part of of a user request processing, you can use the original access token received from your SPA as long as your modules are in a safe environment (e.g. one Kubernates).
In poring over the OIDC spec and numerous implementation guides and articles, I still haven't been able to definitively determine whether the state parameter alone can provide sufficient protection for my particular OIDC use case, though it seems it should be. Given that I am using:
The authorization code flow
An auth server which disallows re-use of codes
A confidential client (using a client secret to authenticate itself with the auth server)
A cryptographically secure, random state, stored in the user's session
is there any attack for which additional measures (nonce or PKCE) provide additional protection? It seems to me that the following are covered:
CSRF Attack
An attacker authenticates using her own account, gaining an authorization code, then tricks the user into visiting the client's redirect endpoint using her code, logging the user into her account. This scenario is prevented: the client compares state in the user's session (if any) to state in the request, finds a mismatch, and rejects the request.
Code Replay Attack
After a user has logged in, an attacker gains access to their authorization code (by, e.g., inspecting browser history on a shared machine), then uses that code with the client's redirect endpoint to trigger a token exchange, logging the attacker into the user's account. This scenario is prevented: the user has previously exchanged the code for a token, and the auth server will not allow it to be reused.
MITM Attack
An attacker is able to read plaintext traffic between the user agent and the client or the auth server (e.g. malware, corporate networks which break TLS). This scenario is unable to be mitigated, as an attacker would be privy to all information necessary to recreate the user's session on their own machine.
Is my understanding correct in all of the above?
One problem with the state parameter alone is that it is a client side validation and it is up to each client to verify this parameter. However, not every client performs this validation and that is a problem.
by adding PKCE, we get a server-side validation and that means that badly implemented clients will not be able to authenticate and the identity provider can enforce/require that PKCE is used.
I'm trying to allow access to our publicly facing APIs to approved Single Page Applications only.
We currently use OAuth 2.0 to control access to our APIs. The high level scenario is that our users will access our publicly available SPA, provide their username and password, and then be able to use the SPA which in turn will be able to use our APIs.
The current best practice for OAuth 2.0 with SPA is to use the authorisation code grant with a client id but without the client secret, as obviously an SPA cannot keep any secrets.
My question is how can we prevent a third party SPA from accessing our APIs. I.e. they could extract the existing client_id from our SPA and request an authorisation code in the same way as our first party SPA. Assuming they can persuade a user to login they can then access our APIs.
Is the pre-registered redirect URL the only defence in this scenario? If so, does that mean that if we switch to using the resource owner credentials grant for a better user experience (not recommended I know) there would be no protection from third party apps at all?
I've read the various RFCs for OAuth and this page in particular is very useful but doesn't quite answer my question:
https://auth0.com/blog/oauth2-implicit-grant-and-spa/
Indeed the pre-registered Redirect URI is the only defense mechanism in this case of a public Client when using the so-called Implicit grant type. An attacker may trick the user in starting the flow but will not receive the issued token on a Redirect URL that it controls. This is similar to tricking the user into starting any other login flow.
Since the attacker does not obtain a token (it is still delivered on the intended Redirect URI controlled by the Client) he cannot access your APIs, even if he can persuade the user to login.
When the attacker controls DNS things become more dangerous but that goes for a lot of things outside of OAuth 2.0 as well. In general: delivering tokens to an in-browser app is going to suffer from this type of vulnerability regardless of the protocol used.
Switching to Resource Owner Password Credentials has a lot of drawbacks, including one where the attacker can present an app similar to yours to obtain the username/password (which also block you from upgrading to multi-factor authentication as the other grant types would allow you to).
In summary: there is protection against it although not super strong.
FWIW: the latest OAuth 2.0 best practices suggest that tokens should no longer be directly delivered to the Redirect URI but use an intermediate short-loved one-time usage Authorization Code instead to allow the SPA to get its tokens in an XHR call directly from the token endpoint.
I'm trying to implement authentication/authorization in my solution. I have a bunch of backend services(including identity service) under API Gateway, "backend for frontend" service, and SPA (React + Redux). I have read about OAuth2.0/OpenIdConnect, and I can't understand, why I shouldn't use Resource owner password flow?
A client ( my backend for frontend server ) is absolutely trusted, I can simply send users login/password to the server, then it forwards them to Identity server, receives the access token && refresh token and stores refresh token in memory(session, Redis, etc), and send the access token to SPA, which stores it in local storage. If SPA will send a request with the expired access token, the server will request a new one using refresh token and forwards the request to API Gateway with the new access token.
I think in my case a flows with redirects can provide worth user experience, and are too complicated.
What have I misunderstood? What potholes I'll hit if I'll implement authentication/authorization as I described above?
OAuth 2.0 specification's introduction section gives one key information on the problem it tries to solve. I have highlighted a section below,
In the traditional client-server authentication model, the client
requests an access-restricted resource (protected resource) on the
server by authenticating with the server using the resource owner's
credentials. In order to provide third-party applications access to
restricted resources, the resource owner shares its credentials with
the third party
As a summary what OAuth wants to provide is an authorization layer which removes the requirement of exposing end user credentials to a third party. To achieve this it presents several flows (ex:- Authorization code flow, Implicit flow etc.) to obtain tokens which are good enough to access protected resources.
But not all clients may able to adopt those flows. And this is the reason OAuth spec introduce ROPF. This is highlighted from following extraction,
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application.The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viable.
According to your explanation, you have a trust relationship with client. And your flow seems to be work fine. But from my end I see following issues.
Trust
The trust is between end user and the client application. When you release and use this as a product, will your end users trust your client and share their credentials.? For example, if your identity server is Azure AD, will end users share Azure credentials with your client.?
Trust may be not an issue if you are using a single identity server and it will be the only one you will ever use. Which brings us the next problem,
Support for multiple identity servers
One advantage you get with OAuth 2 and OpenID Connect is the ability to use multiple identity servers. For example, you may move between Azure AD, Identityserver or other identity servers which of customer's choice (ex:- they already use on internally and they want your app to use it). Now if your application wants to consume such identity servers, end users will have to share credentials with your client. Sometimes, these identity servers may not even support ROPF flow. And yet again TRUST become an issue.!
A solution ?
Well I see one good flow you can use. You have one front end server and a back-end server. I believe your client is the combination of both. If that's the case you could try to adopt authorization code flow. It's true your front end is a SPA. But you have a backend you can utilise to obtain tokens. Only challenge is to connect front end SPA with back end for token response (pass access token to SPA and store other tokens in back-end). With that approach, you avoid above mentioned issues.
I've spent the last few hours reading about the Oauth2 protocol. From my understanding, the main motivation for this protocol is that the resource owner does not have to share their credentials with 3rd party (client) applications, only the resource server.
In this post, I have used the roles as defined in the Oauth2 RFC. However, I have not distinguished between the resource server and authorization server. I assume for the simplicity that they are the same and refer to them as "resource server".
I can see two different chain of events. Assume that both scenarios start with a resource owner with the intent to let a client access a protected resource.
Case 1, GUI provided by the resource server
Client forwards resource owner to the resource server's login page.
Resource owner provides his/her credentials at the resource server's GUI.
On success, the resource server forwards the resource owner to the Client and provides the user client with a token.
Case 2, GUI provided by the Client
The client asks the resource owner to provide his/her credentials to its own GUI.
The client sends the provided credentials to the resource server.
On success, the client obtains a token and access to the resource server.
My concern is case 2. How hard would it be for the client to obtain full privileges on the resource server if it, instead of authenticating as a client, authenticates as the resource owner? The RFC states the following as a reason to use OAuth2 instead of letting the client handle the resource owners credentials:
"Third-party applications gain overly broad access to the resource
owner's protected resources, leaving resource owners without any
ability to restrict duration or access to a limited subset of
resources."
The RFC further states:
"Third-party applications are required to store the resource
owner's credentials for future use, typically a password in
clear-text."
This could very well be saved by the client in case 2.
So... Can you assume that a client that implements Oauth2 (In case 2) is more secure than one that does not? Is it possible for a resource server to implement mechanisms to prevent such things as these?
You can assume that using a proper OAuth2 implementation your system is more secure than a conventional user/pass based system.
Case 1 is clearly superior since no user credentials are exposed to the client.
Case 2 is only a possibility, many OAuth2 providers don't support it at all. Even the standard discourages using it, it seems to be there only as a fallback when the plain old user/pass based logic still must be used for some strange reason. This case is still slightly better as the client application has the possibility not to store your credentials at all. The specified credentials can be dropped right after creating the OAuth request and only the granted tokens should be stored. Gaining a refresh token, there is no need to ask for your user/pass again.
Note that stealing the tokens from the application is still a security risk, but the thief won't have full privilege with your credentials, will only have the access rights you have granted to the application. Furthermore, access tokens expire and the provider should support revoking refresh tokens.
Consider case2:
Lets say the resource owner has provided his/her credentials to the client and as you stated the client has to store the password somewhere in plain text form.
1) But can we trust the client that it would not access any information without your permission ??
2) what if someone hacks the client database and gain access to all the credentials which may contain sensitive information like netbanking passwords etc..,??
so to prevent these security-issues, the resource owner deals directly with resource server and sets the permissions for the client to access only information which it wants and not a bit more. Then the server issues a token(like a gatepass) to the client and whenever the client needs some information it has to send the token.
so its best not to give the client our credentials for security reasons.