I am implementing an App Store for my application where third-party developers can build there own apps based on my API. I have everything working and understand the concepts of OAuth 2.0, but I don't see how an external app can have timeless access with an access code that expires after one hour. Now you can use a refresh token to request a new one, but that one expires after some time too.
So how can an external app continuously connect to my API when the user of that app allows it only once?
My authorization codes expire after 10 minutes, the access tokens after 1 hour and the refresh tokens after 2 weeks.
I don't see how the app can retrieve data after those periods of time without the user re-allowing/re-installing the application through oauth.
How are bigger companies like Facebook etc. approaching this? Do they have an access token that never expires?
Expanding on my comment, the general recommendation when using bearer tokens is that their lifetime should be reduced in order to mitigate the impact of an access token being compromised.
On the other hand, asking the user credentials every hour or so would be an UX nightmare so OAuth 2.0 has the notion of refresh tokens which will normally have a longer lifetime allowing the application to request a new access token without requiring user intervention.
I'm unfamiliar with the implementation details around Facebook persistent tokens so I won't comment on that, but they are most likely safe. However, you're not Facebook, so my recommendation would be for you to follow public standards like OAuth 2.0/OpenID Connect instead of trying to provide a customized approach.
Regarding your comment about refresh tokens that never expire, it's an acceptable solution, but their lifetime is just one part of the equation. You should consider if they are multi-use or single-use, they can only be used by the client application that they were issued to, they should not be used by browser-based applications due to the difficulties of ensuring secure storage, etc.
Related
Is there a standard mechanism in Open ID Connect to kill an active session?
Say a client has an Access token set to expire in 2 minutes. Someone from a central location logs the user out. The idea to prevent that access token from being viable on the very next request as opposed to when the token expires.
This would require Web APIs to contact the authorization server on every single request, which would cause performance problems.
It is standard to use short lived access tokens as the best middle ground. Most commonly this is around 30 or 60 minutes by default.
When reviewing OAuth behaviour in areas like this it can be worth comparing to older systems:
It was never possible to revoke cookies in the manner you describe - so security is not made worse by using OAuth 2.0 based solutions
Typically it is possible to centrally revoke refresh tokens though, so that the next token refresh requires a new login.
There are a couple of drafts that are helpful depending on your specific implementation:
https://openid.net/specs/openid-connect-session-1_0.html
https://openid.net/specs/openid-connect-backchannel-1_0.html
https://openid.net/specs/openid-connect-frontchannel-1_0.html
Several OIDC products are using these methods currently:
https://backstage.forgerock.com/docs/am/6/oidc1-guide/#openam-openid-session-management
https://www.ibm.com/support/knowledgecenter/SSD28V_liberty/com.ibm.websphere.wlp.core.doc/ae/twlp_oidc_session_mgmt_endpoint.html
Several Others also.
In an Open API world, Tokens are the door key (issued to anyone with a valid Client Id and Secret). Tokens allow anybody who has them to access a resource. As such, they are as critical as passwords.
Example: A 3rd party Native App wanting to access your APIs. The app uses the 'Client Id and Secret' to request for an 'Access Token'. This access token to be used for subsequent API calls.
Concern: Usually 'Access Tokens' have a longer TTL. When they are stored in the Mobile App/Client mobile device and if someone gains access to it, they will be able to replay API calls from a different source using this access token and the API URI.
How do you prevent such replay attacks (when access token is
compromised from the 3rd party app) for API calls ?
What secure practice do you follow to allow your consumers/clients
to securely store the 'Access Tokens' ?
In an Open API world, Tokens are the door key (issued to anyone with a valid Client Id and Secret).
I like this analogy :)
Tokens Importance
Tokens allow anybody who has them to access a resource. As such, they are as critical as passwords.
Well even more critical, because they control access to the API, thus an automated attack with a stolen token can ex-filtrate all the data behinhd that API in a matter of seconds, minutes or hours, depending on the size of it, and if rate limiting or other type of defenses are in place or not, and this as a name, Data Breach, and fines under GDPR can be huge, and may even put the company out of business or in serious difficulties.
Access Tokens with Refresh Tokens
Example: A 3rd party Native App wanting to access your APIs. The app uses the 'Client Id and Secret' to request for an 'Access Token'. This access token to be used for subsequent API calls.
Concern: Usually 'Access Tokens' have a longer TTL. When they are stored in the Mobile App/Client mobile device and if someone gains access to it, they will be able to replay API calls from a different source using this access token and the API URI.
The access token should be at least short-lived, and the client, mobile app or web app, should never be the ones requesting it to be issued, instead their respective back-ends should be the ones requesting it to the OAUTH provider, and use the refresh token mechanism to keep issuing short lived tokens, that should be in the range of a few minutes. This approach limits the time a compromised token can be reused by malicious requests.
So I would recommend you to switch to use refresh tokens, that will keep the access tokens short lived while refresh tokens can be long lived, but in the hours range, not days, weeks or years.
Example of refresh tokens flow:
Sourced from: Mobile API Security Techniques - part 2
NOTE: While the above graphic belongs to a series of articles written in the context of mobile APIs, they have a lot of information that is also valid for APIs serving web apps and third party clients.
By using the refresh tokens approach, when a client request fails due to an expired short lived access token, then the client needs to request a new short lived access token.
The important bit here is that the refresh token should not be sent to the browser or mobile app, only the short lived access token can be sent, therefore your third party clients must kept refresh tokens private, aka in their backends, therefore they MUST NOT send refresh tokens from javascript or their mobile app, instead any renewal of the short lived access tokens MUST BE delegated to their backends.
This is a good improvement, but this only identifies who is making the request, not what is making it, therefore your APIs continue without being able to totally trust in the request they receive as coming from trusted sources.
Oh wait a bit... who and what is getting me confused. Well your aren't the only one, and this is indeed a common misconception among developers.
The difference between who and what is accessing the API server.
This is discussed in more detail in this article I wrote, where we can read:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
If the quoted text is not enough for you to understand the differences, then please go ahead and read the entire section of the article, because without this being well understood you are prone to apply less effective security measures in your API server and clients.
API Replay Attacks
How do you prevent such replay attacks (when access token is compromised from the 3rd party app) for API calls ?
Well this is a very though problem to solve, because your API needs to know what is making the request, and it seems that now is only able to know the request was made in the behalf of some who.
For a more in depth approach on mitigating API replay attacks you go and read the section Mitigate Replay Attacks from this answer I gave in another question:
So you could have the client creating an HMAC token with the request url, user authentication token, your temporary token, and the time stamp that should be also present in a request header. The server would then grab the same data from the request and perform it's own calculation of the HMAC token, and only proceed with the request if it's own result matches the one for the HMAC token header in the request.
For a practical example of this in action you can read part 1 and part 2 of this blog series about API protection techniques in the context of a mobile app, that also features a web app impersonating the mobile app.
It has some code examples for the HMAC implementation, so I really recommend you take a look into, but bear in mind that HMAC only makes it a little more difficult to crack, not impossible.
So this is a very hard problem to solve when the access token belongs to a web app, but it's doable in the case of a mobile app that uses a Mobile App Attestation solution, and this is described in this section of another article I wrote, from where I will quote the following text:
In order to know what is sending the requests to the API server, a Mobile App Attestation service, at run-time, will identify with high confidence that your mobile app is present, has not been tampered/repackaged, is not running in a rooted device, has not been hooked into by an instrumentation framework(Frida, xPosed, Cydia, etc.), and is not the object of a Man in the Middle Attack (MitM). This is achieved by running an SDK in the background that will communicate with a service running in the cloud to attest the integrity of the mobile app and device it is running on.
For defending your API when used by mobile apps I recommend you to read the sections Securing the API Server and A Possible Better Solution from this answer I gave for the question How to secure an API REST for mobile app? (if sniffing requests gives you the “key”). For web apps I recommend you to go and read the section Web Application from my answer to the question How do I secure a REST-API?.
Storing Access Tokens
What secure practice do you follow to allow your consumers/clients to securely store the 'Access Tokens' ?
Well in web apps all it takes to extract any token is to hit F12 and look for them, but in mobile apps you need to reverse engineer them.
For a mobile app you can stat by looking into the repository android-hide-secrets to understand the several ways of hiding them, where the most effective is to use native C code, by leveraging JNI/NDK interfaces provided by Android. You can see more real use demo apps using this approach in the repo currency-converter-demo and the app for the shipfast-api-protection-demo. For example see here how configuration is loaded from the C code, by using JNI/NDK approach. But bear in mind that while this makes very hard to reverse engineer statically the mobile app binary to extract secrets, it doesn't provide any security from an attacker to go and use and instrumentation framework to hook into the code that returns the secret from the C code, or to perform a MitM attack to intercept the requests between the mobile app and the backend, thus getting hold of the secret you protect so well.
Mobile apps can solve this by using a Mobile App Attestation solution to not have any secrets at all in their code, therefore if you have read the link I provided previously for defending your API when used by a mobile app, then you will be already more familiar with how a Mobile App Attestation works, and be able to better understand why you may want to have your clients using your API like this:
So your API would be sitting along side the ones already in the APIs section, and the secret to access it is no longer in the public domain, instead is safely stored in the Reverse Proxy vault. To note that the green key is provided during runt time by the Mobile App Attestation service in the cloud, and the mobile app doesn't know if is a valid or an invalid JWT token. If if you have done yet, please go and read the link I already provided to the other answer, so that you can understand in more detail how the attestation works.
In conclusion this approach doesn't benefit only your API, because it also improves the overall security for the mobile apps of your clients.
GOING THE EXTRA MILE
As usual I am not able to finish a security related answer without recommending the excellent work of the OWASP foundation:
The Web Security Testing Guide:
The OWASP Web Security Testing Guide includes a "best practice" penetration testing framework which users can implement in their own organizations and a "low level" penetration testing guide that describes techniques for testing most common web application and web service security issues.
The Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
As said in OAuth2 rfc6749
The implicit grant type is used to obtain access tokens (it does not
support the issuance of refresh tokens) and is optimized for public
clients known to operate a particular redirection URI. These clients
are typically implemented in a browser using a scripting language
Refresh tokens are not suitable for implicit grant.
My question is:
How a mobile app, will refresh the access_token once it expires?
How the big ones in the market are doing this? Which practices they follow?
I know it is not following security recomendations, but it´s a good practice to make an long-lived access_token in this case? It can get annoying to need to re-authenticate each 30 min you use an app, or you close and reopen it.
As necessary permissions don´t change, a silent log-in on every app start, will be a choice to consider?
You don't necessarily need a refresh token to allow continued usage once an access token expires. If you must insist your clients use the implicit flow, then they may be able to make use of cookies and redirects to keep getting short-lived tokens without user interaction. Providing your client apps are using an HTTP agent which can use permanent cookies. e.g. apps that run in a web browser.
The key then is keeping the user signed into the identity provider the first time the token is requested.
This is done for example by the Identity provider (you I guess?) creating an HTTP cookie for the user agent to persist. Most big identity providers will do this - i.e. keep you signed in.
Now, when the token expires your client app will send the user back through the Oauth process again but, because the user has remained logged in to the identity provider, the identity provider can authenticate the user from the cookie without prompting for credentials.
If your clients instigate this token renewal on a background thread they can request the token as normal and, through the magic of HTTP redirects and cookies, get back a new token from you with no user action required.
Again - this alternative to refresh tokens relies on the client device being able to utilise permanent cookies, and your users remaining signed in and your auth server handling http cookies. If your clients are using native apps this solution may not work.
As in the future you will have 100s of clients maybe your auth plaform should offer different auth flows to different clients.
This article on mobile apps and implicit flow may be of interest to you.
Native apps are supposed to use the Auth code grant. So you can use refresh tokens. There is an RFC that discusses reasons (mainly security) for that as well as platform specific details. There is an important implication - the /token endpoint of your OAuth2 provider should not require authentication for getting tokens, because your application cannot keep its client secret safe.
OK. So i need some guidance as I am a total iOS authentication noob.
I have a simple app. Users can login to the app, and send messages to friends. There is a web server and a MySql Database that holds the users and login information.
Question: How do I authenticate a user when he logs in safely and securely?
I have spent the last several hours hurting my brain on the following authentication stuff i found from google:
OAuth 1.0 - is said to be good. But it is a protocol and not a library. Do i have to implement this from scratch? Is this even needed in my case for authentication?
OAuth 2.0 - it seems that some sites are using this. I have the same questions for this as version 1.0. I also saw this this message from the library's lead creator literally saying f*** version 2.0 because it was bad for security. But yet so many still use it. Is it dangerous?
The creator of 2.0 has now gone on to make a completely other library because of how bad 2.0 was and because of how unscalable 1.0 was. His library is called OZ. Should I be using this for my server?
I see AlamoFire/ AFNetworking have basic authentication shown in their documentation. Should i just screw the oAuth stuff and just use theirs?
Being new to the authentication thing, all this is very confusing to me. Can anyone knowledgeable in this provide some guidance?
I am currently in the process of creating a cross-platform application and have spent quite some time researching this!
My approach to the project is using a ASP.NET Web API using OWIN middleware.
This uses bearer tokens to authenticate the user.
Using Microsoft.Identity you can limit endpoints down to roles or even individual users (Autherization)
Currently I create a user on the REST API, They log-in at the /token endpoint and then receive a token. This token is then saved to the Apple key chain and can be used to authenticate the user for further requests to the API.
As long as you use SSL this is a secure method and is used widely in many applications.
This approach uses OAuth2 also, so you'll be albe to easily integrate Facebook/Google/etc integration.
Here is a link to the Microsoft Documentation for some further reading on how I did it:
http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
Currently this is working perfectly for me for an angular front-end but would work exactly the same in iOS except you may want to save the token to the KeyChain Storage.
We mostly use OAuth 2 creating custom system on iOS to handle the authentication.
Nothing is ever bullet-proof but the 2 token system decreases the chance for stealing credential quite nicely.
The AlamoFire, AFNetworking or any other libraries you amy find have nothing to do with this though. What type of credentials you use depends on your choice or rather the choice of the API. You may use these tools to ease your communication with the API though.
So what the idea behind this is you will try to send your user name and password only once when logging in and then you will receive the two tokens which are further used to communicate. This will decrease a chance for someone to intercept the request with the user name and password which are the ultimate key to get the access to the user data.
Next is "refresh token" which is used to receive a new "access token". This call should be made every few hours or so (controlled by the API). If someone was to steal this token he would be able to use it to get further access for an infinite duration or until the owner chooses to invalidate the refresh tokens (this is what happens when you click "log out from all devices"). So this is still quite bad if someone gets it.
Then there is the "access token" which is used for each and every further request to the server. These tokens have a limited time till they are invalidated so if someone was to intercept it somehow he would have the access to the data for the duration of the token.
So assuming this is the procedure that is done on the backend this is what you need to do:
If you have the access token and is valid simply use the service
If you receive the error that the access token is invalid you need to refresh the access token using your refresh token
If refresh token reports an error you need to navigate back to the login screen
If the app has no refresh token then simply go to the login screen
There are some other things that are nice to cover such as if the request reports an invalid token you should pend the request, refresh the token and then repeat the call to the pending request. A system around this may be quite large.
This is pretty much it about the tokens and authentication but there are other parts of the communication which increase the security such as using a https secure connection. When talking about security you must take a look into every part of the communication.
I am just getting started working with Google API and OAuth2. When the client authorizes my app I am given a "refresh token" and a short lived "access token". Now every time the access token expires, I can POST my refresh token to Google and they will give me a new access token.
My question is what is the purpose of the access token expiring? Why can't there just be a long lasting access token instead of the refresh token?
Also, does the refresh token expire?
See Using OAuth 2.0 to Access Google APIs for more info on Google OAuth2 workflow.
This is very much implementation specific, but the general idea is to allow providers to issue short term access tokens with long term refresh tokens. Why?
Many providers support bearer tokens which are very weak security-wise. By making them short-lived and requiring refresh, they limit the time an attacker can abuse a stolen token.
Large scale deployment don't want to perform a database lookup every API call, so instead they issue self-encoded access token which can be verified by decryption. However, this also means there is no way to revoke these tokens so they are issued for a short time and must be refreshed.
The refresh token requires client authentication which makes it stronger. Unlike the above access tokens, it is usually implemented with a database lookup.
A couple of scenarios might help illustrate the purpose of access and refresh tokens and the engineering trade-offs in designing an oauth2 (or any other auth) system:
Web app scenario
In the web app scenario you have a couple of options:
if you have your own session management, store both the access_token and refresh_token against your session id in session state on your session state service. When a page is requested by the user that requires you to access the resource use the access_token and if the access_token has expired use the refresh_token to get the new one.
Let's imagine that someone manages to hijack your session. The only thing that is possible is to request your pages.
if you don't have session management, put the access_token in a cookie and use that as a session. Then, whenever the user requests pages from your web server send up the access_token. Your app server could refresh the access_token if need be.
Comparing 1 and 2:
In 1, access_token and refresh_token only travel over the wire on the way between the authorzation server (google in your case) and your app server. This would be done on a secure channel. A hacker could hijack the session but they would only be able to interact with your web app. In 2, the hacker could take the access_token away and form their own requests to the resources that the user has granted access to. Even if the hacker gets a hold of the access_token they will only have a short window in which they can access the resources.
Either way the refresh_token and clientid/secret are only known to the server making it impossible from the web browser to obtain long term access.
Let's imagine you are implementing oauth2 and set a long timeout on the access token:
In 1) There's not much difference here between a short and long access token since it's hidden in the app server. In 2) someone could get the access_token in the browser and then use it to directly access the user's resources for a long time.
Mobile scenario
On the mobile, there are a couple of scenarios that I know of:
Store clientid/secret on the device and have the device orchestrate obtaining access to the user's resources.
Use a backend app server to hold the clientid/secret and have it do the orchestration. Use the access_token as a kind of session key and pass it between the client and the app server.
Comparing 1 and 2
In 1) Once you have clientid/secret on the device they aren't secret any more. Anyone can decompile and then start acting as though they are you, with the permission of the user of course. The access_token and refresh_token are also in memory and could be accessed on a compromised device which means someone could act as your app without the user giving their credentials. In this scenario the length of the access_token makes no difference to the hackability since refresh_token is in the same place as access_token. In 2) the clientid/secret nor the refresh token are compromised. Here the length of the access_token expiry determines how long a hacker could access the users resources, should they get hold of it.
Expiry lengths
Here it depends upon what you're securing with your auth system as to how long your access_token expiry should be. If it's something particularly valuable to the user it should be short. Something less valuable, it can be longer.
Some people like google don't expire the refresh_token. Some like stackflow do. The decision on the expiry is a trade-off between user ease and security. The length of the refresh token is related to the user return length, i.e. set the refresh to how often the user returns to your app. If the refresh token doesn't expire the only way they are revoked is with an explicit revoke. Normally, a log on wouldn't revoke.
Hope that rather length post is useful.
In addition to the other responses:
Once obtained, Access Tokens are typically sent along with every request from Clients to protected Resource Servers. This induce a risk for access token stealing and replay (assuming of course that access tokens are of type "Bearer" (as defined in the initial RFC6750).
Examples of those risks, in real life:
Resource Servers generally are distributed application servers and typically have lower security levels compared to Authorization Servers (lower SSL/TLS config, less hardening, etc.). Authorization Servers on the other hand are usually considered as critical Security infrastructure and are subject to more severe hardening.
Access Tokens may show up in HTTP traces, logs, etc. that are collected legitimately for diagnostic purposes on the Resource Servers or clients. Those traces can be exchanged over public or semi-public places (bug tracers, service-desk, etc.).
Backend RS applications can be outsourced to more or less trustworthy third-parties.
The Refresh Token, on the other hand, is typically transmitted only twice over the wires, and always between the client and the Authorization Server: once when obtained by client, and once when used by client during refresh (effectively "expiring" the previous refresh token). This is a drastically limited opportunity for interception and replay.
Last thought, Refresh Tokens offer very little protection, if any, against compromised clients.
It is essentially a security measure. If your app is compromised, the attacker will only have access to the short-lived access token and no way to generate a new one.
Refresh tokens also expire but they are supposed to live much longer than the access token.
I've written a little about this because I was pondering the reasoning myself today.
https://blog.mukunda.com/cat/2023/refreshing-access-tokens.txt
Essentially, I think the main security boost is only there if the refresh token does not remain the same over its lifetime.
Let's say someone steals your tokens from your browser cookies because they had access to your device temporarily.
If they use the refresh token, and the refresh token changes, then you have feedback – you are logged out. That can seem rightfully suspicious to careful users who can then take action and revoke all tokens.
If the refresh token doesn't update upon each use, then it is harder to notice that someone has access in tandem. (Chances are, if does update, then it might update from your device automatically before the attacker can even get to use it.)
If the refresh token does not get updated each time you use it, then I don't see any boost in security from the strategy, since it will be right next to the access token and client secrets.
So, why access tokens? It is so you can check that your credentials are valid regularly.
Do refresh tokens expire? Yes, but usually after a few months if you have "remember me" ticked. There's no expiration time in the spec, so you just go until it fails. Services that require longer unmonitored sessions might have secret credentials so they can refresh their refresh token.
Update:
I also glossed through the OAuth 2.0 specification and see the same reasoning, though it emphasizes that the invalid authentication feedback can be caught on the server side. That is a great point – the server can automate revoking the token if it is compromised.
If a refresh token is compromised and subsequently used by both the attacker and the legitimate client, one of them will present an invalidated refresh token, which will inform the authorization server of the breach.