Related
When a user is authenticated by the server, the server sends, according to the most common implementation I found(which is were my question stems from), sends BOTH access token and the refresh token to the client.
-- My first questions is:
What is the point of sending both tokens to the client if, to my understanding, we have the refresh token in the first place to help us mitigate the consequences of an access token being leaked?
If both tokens are sent to the client and are stored together (in the same place, localStorage, sessionStorage, one in former, one in latter - I don't think it matters to the questions how we decide to store them on the client), if an attacker manages to steal the access token, then it is safe to assume he would also find a way to steal the refresh token from the same client since they are most likely stored together. I don't understand why most implementations and answers I find online mention sending both tokens to the client since its basically like putting all eggs in the same basket.
(A big part of my confusion comes also from the fact that those answers and implementations don't mention anything about storing the tokens in HttpOnly cookies, which I'd think would be a common practice if we want to prevent tokens getting leaked, so I'm getting a feeling I'm missing something)
-- My second question would be:
Would it be a correct solution then to persist the access and refresh tokens upon issue in an "accessT <-> refreshT"(like a key=value pair) table on a server, so that only one token is ever sent to the client - the access token? And when that access token expires the process of "refreshing" would be the following:
ResServer = resource server
AuthServer = authorization server
The request with the expired token is sent to the ResServer.
ResServer checks and sees that the access token has expired.
ResServer then sends a request to the AuthServer to look up the refresh token by the access token in the table mention above.
If AuthServer finds a refresh token by using the expired access token as a key - good, AuthServer generates a new access token.
AuthServer then responds to the ResServer with that new access token.
Having received a positive response, ResServer proceeds on with it's usual flow for authorized users.
^^ This seems to me to be a more rational way of keeping the refresh token safe - making it serve its primary function, which is why I don't understand why most other implementations on the web always mention sending both tokens to the client.
-- And my third question is:
Not having much experience implementing microservices, I am confused about why we would ever prefer to implement this token back and forth approach, when, from what I understand, the entire point of tokens is that they are supposed to be a stateless solution(well, the refresh token is always kept on the server regardless of implementation, which confuses me even more about that "stateless" part). Doesn't it make more sense to just use cookies that basically serve the same function, but are easier to implement, secure by default("Secure", "HttpOnly" flags), and, as it appears to me, are much easier to revoke in can they are leaked?
Thanks you for taking your time to read this entire post, I appreciate your help.
Regarding your first question:
The advantage of having two tokens is not that you can store one of the tokens more securely. The advantage is that if the Resource Server gets compromised, it does not allow lateral escalation. For this to make sense, your access tokens must be bound to specific resource servers.
As an example, assume you have two resource servers ResA and ResB. Then your Authentication server would allow you to obtain one access token for each of these servers, and one refresh token (that allows refreshing both access tokens). If resource server A gets compromised (or the network path between the client and that server), then the access token to that server will expire at some point, and the attacker will not be able to access resource server B with the access token issued for resource server A. At the same time, only the legitimate user is able to refresh their tokens, since they only provide the refresh token to the AuthServer, such that a compromised or malicious resource server never sees at.
That leads directly to your second question:
Your proposed model prevents key rollover. If a resource server gets compromised, all its tokens are eternally compromised, unless the Authentication Server voids all refresh tokens. Voiding refresh tokens would lead to users being logged out of all resource servers (even those who are not compromised).
As an example, consider the following scenario: Tour authentication provider is a large public service, such as "Sign in with Google", with thousands of resource servers using this service. Now one of those resource servers gets compromised, and attackers steal the authentication tokens.
In the commonly employed auth-refresh token pattern, the auth tokens will expire, which means that the service will be inaccessible for attackers as soon as the used vulnerability is fixed + the time it takes for tokens to expire (since the attackers could not get hold of the resource tokens), without the need for the AuthServer to do anything. Additionally, the AuthServer does not need to keep track of the issued tokens, if it uses cryptography to sign the tokens with a private key only known to the auth server, as it (and all resource servers) can trivially verify token authenticity by validating against a public key (please also see the end of my answer).
In your proposed approach, the AuthServer (which is Google in this example) would have to void all refresh tokens OR they would have to selectively delete all auth-refresh token pairs for the affected resource server from the key-value store. That key-value store will be gigantic, since it has to contain EVERY auth token ever issued, for any service that uses "Sign in with Google", and apart from storage costs, this delete operation will take quite some time.
Regarding your last question:
You can store access tokens in Cookies. There is a bunch of advantages to that (including the Secure and HttpOnly flags that you mentioned). It has two disadvantages: If you want to implement something like a CLI client that runs outside of a browser, you would have to implement Cookie handling. The other disadvantage is the CSRF risk as Cookies are automatically sent on every request. Using local storage prevents this, as an external website cannot access the local storage of your website to extract the token.
In the end it comes down to the concrete scenario, if Cookies or Local Storage + Custom Header are the preferable solution.
However, I think you have a misconception regarding statefulness:
Access and Refresh tokens do not need to be stored on the server. Instead, the Auth Server signs the Token Contents with a cryptographic private key, before sending them to a client. In doing so, the AuthServer includes an expiration date in the token, which is included in the signed content.
To validate the token, the Resource Server (or the AuthServer) checks if the signature comes from the AuthServer's private key, and then checks if the expiration date has passed. In particular, the resource server does not need to communicate with the AuthServer, apart from obtaining its Public Key from time to time. This makes this solution scale really well for very large deployments. See the Microsoft Azure docs, which do a great job on explaining the difference between Auth and Refresh tokens.
What you are alluding to are traditional session ids, which are stored on the server until they expire. Thats obviously a much simpler solution, and works well for smaller, more monolithic applications. It just does not work for hyper scalers.
My service allow any HTML documents to be converted to PDF using a POST request.
It is mostly used on the backend of my client's server and thus, the API key used for the communication is kept private.
Now, I'm thinking of a way to let my client's visitors be able to call my service on behalf of my client API key, without exposing this secure API Key.
My main issue here is security. If my client add an XHR POST requests that contains the API key, someone can take that API key and use it for their own purpose and abusing my client's account.
I could filter by domain, but this is easily spoofed so it's not possible.
I was wondering if there was a way to call a private service and be identified without risking its identity to be stolen, from the client ('s client) side?
If you're providing this sublet for authenticated users, then it's fairly trivial to give them unique keys (something that hashes their user ID or session against the API key and an initial timestamp, and checks it / logs it / looks for brutes before accessing the API). If you're doing it on the open web, without any kind of user authentication, then rate limiting gets very tricky indeed. Generally you'd want to use a combination of session hashes, IP address, operating system and browser data to create an anonymous profile that gets a temporary key on the frontend. One fairly solid way to do this is to force users through a CAPTCHA before serving a temporary key that allows them a limited number of uses of the permanent key. Any user whose ip/browser/session matches the existing attributes of a known client key is shunted to that one (and gets to skip the CAPTCHA); anyone who doesn't match an existing profile gets the CAPTCHA. That makes you a less attractive target for spoofing. On top of that, you should always rate-limit the entire thing, within a reasonable number of hits per day based on what kind of traffic you expect (or can afford), just so you don't have any surprises. This is the minimal security you'd want if your client's money is on the line every time their API key is used. It will require a simple database to store these "profiles", track usage, check for brutes and maintain the currently valid client keys. Client keys should always be expired regularly - either with a time diff against when they were created, or a regular cron process, or a maximum number of uses, etc.
One other thing I frequently do is rate-limit based on a curve. If I think 5 uses per minute is reasonable, for example, then after 5 uses in a minute from a session, each usage adds a delay of a fraction of a second * the number of uses in the last minute, squared, before the data is served.
The best answer would be to put this all behind a login system and secure that.
Assuming that you are using OAuth kind of system, In that case, make use of Access Token Mechanism that provides access to private API/User's data on behalf of User(Client) without exposing his/her credentials or API Key(Authentication key), also the access token can be expired based on the time/usage.
Example: The access token is generated against a single endpoint that can be the Html Conversion endpoint and will be expired once the action completion.
https://auth0.com/docs/tokens/access-token
And following blog post would be helpful to architect your authentication system
https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
there is no good way to do front-end secure storage but my recommendation is :
is an API that used HMAC signing of requests in combination with OAuth authentication. The API key is actually a signing key. they key does not get transferred. The API key can still get found on the front-end but it becomes useless because you still need the OAuth token to send a valid request.
i know users will have to login in, but you can see this as an advantage because atleast you can log who is using the app by getting information from oauth.
please consider back-end secure storage!
You can use JWT tokens in my opinion. On the basis of username, password or any other info you can generate unique jwt tokens for different users.
Anyone can decipher these jwt tokens but not he unique security token.
If you want to add more more security to tokens, use JWE, encrypted web tokens.
More about these schemes can be found at https://medium.facilelogin.com/jwt-jws-and-jwe-for-not-so-dummies-b63310d201a3
Hashing is a decent option and should be done anyway, but for a fully secure method that wouldn't add too much complexity, you could simply abstract away from the authorization/API key by building your own API to interface with the API. This way you could both limit the kinds of things that can be done with the API key and also completely obscure the API key from the user
I don't think you should always go for user auth or JWT, it just doesn't fit all use cases. The idea of using a Captcha is interesting but also somewhat complex.
If complexity is not an issue I would rather use an infrastructure approach, I'm most familiar with AWS so I'll focus on that. Assuming you can change the host of your front end you can have your site hosted on an S3 bucket, served through a CDN, and create a proxy Lambda function that will hold the logic to call your API and store the API key as an encrypted environment variable. This Lambda you call through an API Gateway that can only be called by a specific IAM role which the S3 bucket also uses. You can also use a Cognito User Pool without authentication.
Going back to a simpler alternative the Captcha approach can be implemented as an attestation provider. I know of two services that do this, Firebase and KOR Connect. Due to Firebase using this approach only for their own resources as of the time of this writing I much rather use KOR Connect as it’s a very simple middleware that basically solves this issue. I won't go into detail about these services as it’s not the main concern of this topic but you can check the documentation their respective links.
I have some questions related to tokens and encryption.
First of all Access Tokens :
Regardless the various attacks(that you need to bear in mind so that you take measures against), would you recommend storing an access token on the client?(localstorage/ cookies).
If yes, will I need to encrypt it and store the encrypted token on the client. However, is that really needed since I am using SSL? You are using SSL to prevent a MIM attack.But since you are using HTTPS, why should we also encrypt the access token?
My second question is related to encryption. For SSL, I understand that I need a certificate (or self-signed certificate to test it locally). However, for encrypting the token, do I need the same SSL's certificate, or can I use an RSACryproProvider to generate a pair of public/private keys?
For Refresh tokens :
I believe the best approach is to save the encrypted refresh tokens in the database. It could be an actual API that reads/Writes refresh tokens in the database. However, the refresh token, must be stored along with some user attribute ie UserId, so you can retrieve it based on i.e userid, email etc. Assuming, I use the UserId, I would encrypt it along with some character and date and store it on the client. Do you agree on that? And also, I am thinking to restrict the access on that API, so that it can only serve requests from a particular server or servers (web farm). What is your opinion about this approach?
I would REALLY appreciate your help, as I am really trying to understand in depth some concepts. If there is something, I don't express correctly, please let me know to rephrase my question.
Thanks
I just implemented Json Web Tokens to my api, but I don't understand how to verify if the user that created the token, is the one that is making the request.
For example, I have the /user/login end point, and I received the user and password for login. Then I create a json web token with the user data inside, and return it. And here is my problem, how do I know that the user that create that token, is the one that is making the request ?.
I found several ways to verify this, for example saving the user-agent + ip of the user and only accept request for that token if the user-agent + ip is xxx, but I am not really sure that is the best way.
I hope you can help me with some tips,
Thanks for all
how do I know that the user that create that token, is the one that is making the request ?.
Because the JWT includes the user ID and is signed, therefore any alterations to the content will be detected. Possession of the token is proof of authenticity
The process of issuing and authenticating with JWT is more or less like this
Issuing new JWT
User performs and authentication using its credentials
The server validate credentials, generate the JWT payload including the user data and some fields such as expiration time or issuer, and signs the token with server private key
The client receives the token and store it (in a secure storage).
Authentication
User sends a request to server. The request includes the JWT, usually in headers or as url param
The server validates the signature with the key, and extracts the user ID to know the requestor. If the signature is not valid rejects the request
Any reason you can't use a standard like OAUTH2 and let the big boys handle security for you? Rolling your own security is usually very difficult to get correct and almost all the major players provide free OATH support.
That said, I'd be hesitant to lead you down a bad path, however I've been in your shoes before so if you must roll your own security, make certain you fully read all of what OWASP has to offer. They offer very detailed threat analysis and also give suggestions that will be invaluable along your journey.
OWASP Threat Analysis
EDIT 1
A good light weight and easy to implement standard is OpenID which as their banner explains is,
A Simple Identity layer on top of OAuth 2.0
See here for a very detailed explanation of how it works:
OpenID-Wiki
Overview
I'm looking to create a (REST) API for my application. The initial/primary purpose will be for consumption by mobile apps (iPhone, Android, Symbian, etc). I've been looking into different mechanisms for authentication and authorization for web-based APIs (by studying other implementations). I've got my head wrapped around most of the fundamental concepts but am still looking for guidance in a few areas. The last thing I want to do is reinvent the wheel, but I'm not finding any standard solutions that fits my criteria (however my criteria my be misguided so feel free to critique that as well). Additionally, I want the API to be the same for all platforms/applications consuming it.
oAuth
I'll go ahead and throw out my objection to oAuth since I know that will likely be the first solution offered. For mobile applications (or more specifically non-web applications), it just seems wrong to leave the application (to go to a web-browser) for the authentication. Additionally, there is no way (I am aware of) for the browser to return the callback to the application (especially cross-platform). I know a couple of apps that do that, but it just feels wrong and gives a break in the application UX.
Requirements
User enters username/password into application.
Every API call is identified by the calling application.
Overhead is kept to a minimum and the auth aspect is intuitive for developers.
The mechanism is secure for both the end user (their login credentials are not exposed) as well as the developer (their application credentials are not exposed).
If possible, not require https (by no means a hard requirement).
My Current Thoughts on Implementation
An external developer will request an API account. They will receive an apikey and apisecret. Every request will require at minimum three parameters.
apikey - given to developer at regisration
timestamp - doubles as a unique identifier for each message for a given apikey
hash - a hash of the timestamp + the apisecret
The apikey is required to identify the application issuing the request. The timestamp acts similarly to the oauth_nonce and avoids/mitigates replay attacks. The hash ensures that request was actually issued from the owner of the given apikey.
For authenticated requests (ones done on the behalf of a user), I'm still undecided between going with an access_token route or a username and password hash combo. Either way, at some point a username/password combo will be required. So when it does, a hash of several pieces of information (apikey, apisecret, timestamp) + the password would be used. I'd love feedback on this aspect. FYI, they would have to hash the password first, since I don't store the passwords in my system without hashing.
Conclusion
FYI, this isn't a request for how to build/structure the API in general only how to handle the authentication and authorization from solely within an application.
Random Thoughts/Bonus Questions
For APIs that only require an apikey as part of the request, how do you prevent someone other than the apikey owner from being able to see the apikey (since sent in the clear) and make excessive requests to push them over usage limits? Maybe I'm just over thinking this, but shouldn't there be something to authenticate that a request was verified to the apikey owner? In my case, that was the purpose of the apisecret, it is never shown/transmitted without being hashed.
Speaking of hashes, what about md5 vs hmac-sha1? Does it really matter when all of the values are hashed with with sufficiently long data (ie. apisecret)?
I had been previously considering adding a per user/row salt to my users password hash. If I were to do that, how could the application be able to create a matching hash without knowing the salt used?
The way I'm thinking about doing the login part of this in my projects is:
before login the user requests a login_token from the server. These are generated and stored on the server on request, and probably have a limited lifetime.
to login the application calculates the hash of the users password, then hashes the password with the login_token to get a value, they then return both the login_token and the combined hash.
The server checks the login_token is one that it has generated, removing it from its list of valid login_tokens. The server then combines its stored hash of the user's password with the login_token and ensures that it matches the submitted combined token. If it matches you have authenticated your user.
Advantages of this are that you never store the user's password on the server, the password is never passed in the clear, the password hash is only passed in the clear on account creation (though there may be ways around this), and it should be safe from replay attacks as the login_token is removed from the DB on use.
That's a whole lot of questions in one, I guess quite a few people didn't manage to read all the way to the end :)
My experience of web service authentication is that people usually overengineer it, and the problems are only the same as you would encounter on a web page. Possible very simple options would include https for the login step, return a token, require it to be included with future requests. You could also use http basic authentication, and just pass stuff in the header. For added security, rotate/expire the tokens frequently, check the requests are coming from the same IP block (this could get messy though as mobile users move between cells), combine with API key or similar. Alternatively, do the "request key" step of oauth (someone suggested this in a previous answer already and it's a good idea) before authenticating the user, and use that as a required key to generate the access token.
An alternative which I haven't used yet but I've heard a lot about as a device-friendly alternative to oAuth is xAuth. Have a look at it and if you use it then I'd be really interested to hear what your impressions are.
For hashing, sha1 is a bit better but don't get hung up about it - whatever the devices can easily (and quickly in a performance sense) implement is probably fine.
Hope that helps, good luck :)
So what you're after is some kind of server side authentication mechanism that will handle the authentication and authorisation aspects of a mobile application?
Assuming this is the case, then I would approach it as follows (but only 'cos I'm a Java developer so a C# guy would do it differently):
The RESTful authentication and authorisation service
This will work only over HTTPS to prevent eavesdropping.
It will be based on a combination of RESTEasy, Spring Security and CAS (for single sign on across multiple applications).
It will work with both browsers and web-enabled client applications
There will be a web-based account management interface to allow users to edit their details, and admins (for particular applications) to change authorisation levels
The client side security library/application
For each supported platform (e.g.
Symbian, Android, iOS etc) create a
suitable implementation of the
security library in the native
language of the platform (e.g. Java,
ObjectiveC, C etc)
The library
should manage the HTTPS request
formation using the available APIs
for the given platform (e.g. Java
uses URLConnection etc)
Consumers of the general authentication and
authorisation library ('cos that's
all it is) will code to a specific
interface and won't be happy if it
ever changes so make sure it's very
flexible. Follow existing design
choices such as Spring Security.
So now that the view from 30,000ft is complete how do you go about doing it? Well, it's not that hard to create an authentication and authorisation system based on the listed technologies on the server side with a browser client. In combination with HTTPS, the frameworks will provide a secure process based on a shared token (usually presented as a cookie) generated by the authentication process and used whenever the user wishes to do something. This token is presented by the client to the server whenever any request takes place.
In the case of the local mobile application, it seems that you're after a solution that does the following:
Client application has a defined Access Control List (ACL) controlling runtime access to method calls. For example, a given user can read a collection from a method, but their ACL only permits access to objects that have a Q in their name so some data in the collection is quiety pulled by the security interceptor. In Java this is straightforward, you just use the Spring Security annotations on the calling code and implement a suitable ACL response process. In other languages, you're on your own and will probably need to provide boilerplate security code that calls into your security library. If the language supports AOP (Aspect Oriented Programming) then use it to the fullest for this situation.
The security library caches the complete list of authorisations into it's private memory for the current application so that it doesn't have to remain connected. Depending on the length of the login session, this could be a one-off operation that never gets repeated.
Whatever you do, don't try to invent your own security protocol, or use security by obscurity. You'll never be able to write a better algorithm for this than those that are currently available and free. Also, people trust well known algorithms. So if you say that your security library provides authorisation and authentication for local mobile applications using a combination of SSL, HTTPS, SpringSecurity and AES encrypted tokens then you'll immediately have creditibility in the marketplace.
Hope this helps, and good luck with your venture. If you would like more info, let me know - I've written quite a few web applications based on Spring Security, ACLs and the like.
Twitter addressed the external application issue in oAuth by supporting a variant they call xAuth. Unfortunately there's already a plethora of other schemes with this name so it can be confusing to sort out.
The protocol is oAuth, except it skips the request token phase and simply immediately issues an access token pair upon receipt of a username and password. (Starting at step E here.) This initial request and response must be secured - it's sending the username and password in plaintext and receiving back the access token and secret token. Once the access token pair has been configured, whether the initial token exchange was via the oAuth model or the xAuth model is irrelevant to both the client and server for the rest of the session. This has the advantage that you can leverage existing oAuth infrastructure and have very nearly the same implementation for mobile/web/desktop applications. The main disadvantage is that the application is granted access to the client's user name and password, but it appears like your requirements mandate this approach.
In any case, I'd like to agree with your intuition and that of several other answerers here: don't try to build something new from scratch. Security protocols can be easy to start but are always hard to do well, and the more convoluted they become the less likely your third-party developers are to be able to implement against them. Your hypothetical protocol is very similar to o(x)Auth - api_key/api_secret, nonce, sha1 hashing - but instead of being able to use one of the many existing libraries your developers are going to need to roll their own.
Super late to the party but I wanted to throw in some additional points to consider for anyone interested in this issue. I work for a company doing mobile API security solutions (approov) so this whole area is definitely relevant to my interests.
To start with, the most important thing to consider when trying to secure a mobile API is how much it is worth to you. The right solution for a bank is different to the right solution for someone just doing things for fun.
In the proposed solution you mention that a minimum of three parameters will be required:
apikey - given to developer at registration
timestamp - doubles as a unique identifier for each message for a given apikey
hash - a hash of the timestamp + the apisecret
The implication of this is that for some API calls no username/password is required. This can be useful for applications where you don't want to force a login (browsing in online shops for example).
This is a slightly different problem to the one of user authentication and is more like authentication or attestation of the software. There is no user, but you still want to ensure that there is no malicious access to your API. So you use your API secret to sign the traffic and identify the code accessing the API as genuine. The potential problem with this solution is that you then have to give away the secret inside every version of the app. If someone can extract the secret they can use your API, impersonating your software but doing whatever they like.
To counter that threat there are a bunch of things you can do depending on how valuable the data is. Obfuscation is a simple way to make it harder to extract the secret. There are tools that will do that for you, more so for Android, but you still have to have code that generates your hash and a sufficiently skilled individual can always just call the function that does the hashing directly.
Another way to mitigate against excessive use of an API that doesn't require a login is to throttle the traffic and potentially identify and block suspect IP addresses. The amount of effort you want to go to will largely depend upon how valuble your data is.
Beyond that you can easily start getting into the domain of my day job. Anyway, it's another aspect of securing APIs that I think is important and wanted to flag up.