Store Access and Refresh Token for Command - oauth-2.0

I plan to develop a command line client for a web API protected by OAuth 2 (JWT). The access and refresh tokens live for five and thirty minutes, respectively. Since the user will use the command line client for longer than five minutes in a sitting (a testing or debugging session, for example), the refresh token needs to be stored on the local computer, so that only one authentication is needed at the beginning of the session, and not later on.
I wonder where I can store the refresh token securely. A text file in the user's home directory might not sound too bad, because that's also the place the user stores all his or her private documents. However, any other application run by the same user could read that token and misuse it.
What are common solutions to such a problem?

Here you can use Resource Owner Password Credentials Grant in which you will use command prompt to get end user credentials and exchange them for tokens. With that, you can think of a way to encrypt received tokens based on end user credentials you got when requesting tokens. So whenever you require to use refresh token, you can prompt end user for their password so that you do not store the password but also you encrypt tokens so no other process can steal them as it is.

Use ROPG as Kavindu says - if you have an implementation that supports refresh tokens
After that you can store tokens in memory or via OS secure storage. The choice is a little subjective and depends on sensitivity of data being accessed
If using OS secure storage then store tokens per app + user, to ensure isolation
An example cross platform component that does this is keytar, which I've used in the past for desktop apps - it is nodejs based -not sure if this works for you:
https://github.com/atom/node-keytar/blob/master/README.md
Sample code that uses it
See the OS Secure Storage section of this write up to understand how the entry can be viewed + managed via built in OS tools:
https://authguidance.com/2018/01/26/final-desktop-sample-overview/

Related

How is "keep logged in" secured in native applications?

I always wondered how native applications like the Dropbox client or any other native application with a serverside service implement the "keep logged in" feature securely.
Do they store the users credentials? Or do the store a never expiring access-token?
How are the credentials / access-token stored? They must be encrypted in any way.
When encrypting the data, how is the key generated? A fix key wouln´t make much sence because the code could be reverse engineered.
Is there a best practice or industry standard for storing credentials / access-tokens securely?
Native apps can use built in secure storage to store OAuth tokens after login:
Tokens are encrypted with a key that is private to the app and user
They are stored in Operating System Secure Storage, eg Windows Credential Manager / MacOS or iOS Key Chain
The refresh token can have a long lived expiry but it is not infinite
Standard libraries usually do the lower level encryption work
The key benefit of course is that the user does not need to log in on every app restart. As an example:
A desktop app of mine deals with OS secure storage via this code.
And the end of this blog post shows the stored credentials.
The same principles apply to mobile:
iOS
Android

OAuth2 app with Touch ID

Is there any way that a third-party app can logically use Touch ID to authenticate to a web service that uses OAuth2?
Say I own a web service that requires authentication using OAuth2. It supports both the implicit and authorization-code grants (although I could add support for other grants if necessary).
A third party has a mobile app that uses this web service. It opens a native web view to authenticate, and loads my auth URL in it. The user enters their username/password on my domain, and I return an OAuth token back to the app.
If this app wants to implement Touch ID to speed up authentication, is there a way to do it that makes sense with OAuth2?
My understanding is that the purpose of the OAuth2 implicit and auth-code grants is to prevent the parent app from having access to the user's credentials. It only gets access to the resulting OAuth token, and that's only valid for a limited time.
With Touch ID, you would typically store the password using Keychain Services. So this obviously requires you to have access to the password.
I suppose they could store the OAuth token in the keychain instead of the password, but then this would only be valid for a short time.
The only answer I've come up with so far is what you allude to at the end: store the OAuth tokens -- but also a long-lived refresh token. How long that refresh token can live is definitely dependent on your specific security needs.
I don't know about any standard flow yet but here are some common considerations. Simply storing long-term credentials (passwords or refresh tokens, even encrypted at rest) would be mixing up security contexts in a way that is hard to audit. When using any local authentication (app-specific unlock PIN, any biometrics, or simply system unlock) it's important to do it in a way that can be verified by the server. So the first step would be device authentication, every instance of your app should use unique client id/client credentials (I suggest to implement Dynamic Client Registration Protocol to help with that but there could be other options). Then, it's a good idea to generate some piece of verifiable key information directly on the device, put it into secure storage (protected by whatever local unlocking mechanism and invalidated whenever biometrics changes or) and use it to generate a MAC of some kind, for example a JWT as a part of jwt-bearer flow (or some new extension to OAuth assertion framework). JWT tokens could include additional metadata (claims) that can provide more context to the server, like it can make informed decisions to force re-authentication in some cases.
To restate:
Device is authorized and issued an unique client credentials pair.
Locally-generated key is saved to the encrypted storage and protected by some local unlock mechanism (system lockscreen, PIN, biometrics, etc.)
The key gets registered with the server and tied to the device.
On unlocking the key is used to generate a JWT that is used as assertion for authenticating with the server.
Seems pretty standard to me, maybe someone should write up a BCP for this after thinking through all the implementation details, current practice, and security considerations.

How to save refresh tokens?

I'm trying to add authentication feature to my application.
The authentication server implements oauth 2.0
I'm not sure how to save the refresh_token. I want to save it to a file, so next time when the application starts and there is a refresh_token available, it can ask for a new access_token. The user won't need to re-login again.
But this doesn't sound secure to me, because if someone copies my file that has the refresh_token to another computer, he can hack into my account.
You are correct with the attack that you describe. Refresh tokens have to be stored securely in order to be used as intended. As I understand, you are building a standalone application. Therefore, you can rely on file system security to prevent a refresh token being copied by an unauthorized user. You may want to use encryption for the refresh token, too, but the key would need to be bound to a user's session at your local machine (otherwise, the user would need to provide it during "sign in" process in order for the application to decrypt the refresh token).
Consider reading the thread from the OAuth WG, that discusses similar problems to the one described and provides some guidance:
https://www.ietf.org/mail-archive/web/oauth/current/msg02292.html
Refresh tokens are used to obtain access (this process requires HTTP Basic Auth). So, unless user has your (id,secret) combination he can't do much about it. However, storage of refresh token must be considered very seriously.
Here's my two cents:
Store your tokens in a DB
Whenever you use refresh token to obtain access token reset the refresh token as well. (Oauth2.0 has this feature, you can let the refresh token unchanged too, but it's wise in terms of security perspective to keep it changing and updating the DB)
Hope this gives some insights!!
You are right about your concern - you should not save the refresh token. By doing so, you jeopardize your client's data (and you know the reason; you wrote it in the question).
oAuth is not supposed to work this way.
You should keep the refresh token in-memory.

dotnetopenauth - How to add extra data in the refresh token?

I'm currently working on a project where an iPad application requires access to an existing web application. The iPad application has been developed internally and is therefore a trusted application. However the data provided by the web application is sensitive so we don't want to store client credentials on the iPad. We also want the ability to revoke iPad access without affecting regular user access.
Given the above, the OAuth2 Resource Owner Password Credentials grant/flow was a good fit for our requirements which we've implemented with DotNetOpenAuth since its an established library.
However, we now require some metadata to be added to the access and refresh tokens for the resource server. The authorization server is adding the metadata via the AuthorizationServerAccessToken.ExtraData property in our implementation of the IAuthorizationServerHost.CreateAccessToken method:
public AccessTokenResult CreateAccessToken(IAccessTokenRequest accessTokenRequestMessage)
{
var accessToken = new AuthorizationServerAccessToken();
// Add some extra data to access token
accessToken.ExtraData.Add("server_parameter1", this.ServerValue1);
accessToken.ExtraData.Add("server_parameter2", this.ServerValue2);
// Set ResourceServerEncryptionKey properties etc
return new AccessTokenResult(accessToken);
}
This does exactly what we want for the access token however the same "ExtraData" is not included in the refresh token which causes an issue when the access token expires and needs to be refreshed because we effectively lose the additional data (since the old access token is discarded).
Can anyone advise if its possible to populate the refresh tokens "ExtraData" in the current version of DotNetOpenAuth in a similar way to the access token?
No, I don't think there is currently a way to embed extra data into the refresh token. Let's talk a bit about why this is.
First off, there is no such thing as a trusted iPad app, whether you develop it or not. The problem is that apps you distribute (even internally) can't keep a secret. Any client_secret, certificate, etc., can be cracked. Therefore apps you distribute can't authenticate themselves to the server. If the server can't authenticate the client, the server can't trust the client.
Now let's look at your scenario a bit more (and if you have more feedback, it may be best to continue the discussion on dotnetopenid#googlegroups.com). The client has data that it wants to eventually end up at the resource server. You're currently trying to pass that data through the authorization server first, then via the access token to the resource server. Why is that? Why not just have the client send the data directly to the resource server along with the access token? If the answer is that the resource server shouldn't trust the client, then what you have by sending it by way of the access token is a false sense of security for the reasons given in the above paragraph. If the client could provide false info to the resource server, it could also provide false data to the authorization server.
One valid use of extra data in the access token is data that the authorization server knows for itself -- not data that came from the client. In which case, it can look up that data each time an access token is minted and doesn't therefore have to be stored in the refresh token.

Verifying a user when backing up data to a server

Note: Although I raise this issue in the context of an iOS app, I don't think it's confined to an app running on that specific OS.
I'm developing an iOS application that will back up user data to a server and I'm trying to figure out the best way to verify server-side that the user being updated is actually the real user. Each user will have an id (uid). If that's all I depended on server-side, then I imagine the process would go like this:
User runs app for the first time
Creates account in the app, which communicates with the server to both create the account on the server and to get a unique "user id" (uid)
App stores this uid so that it can identify the user in subsequent communications with the server
However, if someone were to hack the app on their iphone, they could change the user id value and then that would instantly give them access to/allow them to modify a different user's data.
The current solution I'm considering is that the user receives 2 unique ids, the uid (just an auto-incremented number) and a longer, more complex key string. All communication with the server will therefore have to send along both the uid and the key. The server will verify that they match in order to make sure that the user truly is who the app says it is.
So, my question is two-fold:
Is this the correct way to achieve this? Or is there some other standard method that I should pursue?
If this is the correct approach, what's the recommended way to generate the unique key?
First of all, you can use the more complex value as the user ID to begin with, if you like (e.g. a UUID). Monotonically increasing IDs get hard to manage as your service scales.
You have the same problem a secure web site does when it leaves secure cookies on the browser to remember a session. Those cookies do include the user ID, but must prevent tampering. This is generally done by signing the cookie on the server before sending it back.
So what you'd do is:
Generate the user ID on the server, and use it to create some sort of "auth token" for the client to have to sign in.
Sign the auth token on the server with a secret key that only your server knows.
Send the auth token to the client, where it is stored for all subsequent logins. Transfer the auth token over HTTPS to prevent someone else from snooping it on the network.
When the app goes to login, send up the auth token to the server. If it's been hacked, the signature validation will fail, and you'll know to reject the client.
Consider including a timestamp in the signed token as well, so it expires after some time, forcing the server to regenerate an auth token periodically, which protects you in case your key is compromised. It's hard to do this all fully unless the user himself has a shared secret/password he can use to authenticate periodically as well. Depends on how far you need to go.
Other considerations: If all you know about a user is their generated UID, you don't have any way for that user to come back later from a different iOS device and restore their account there, right? Generally, if the user will be creating anything "valuable" in their account that they'll want access to later, you'll probably want to create a more traditional user account backed by an email address and password or the like, so they can access the account again after reinstalling your app. (This may or may not be relevant to your case.)
I would recommend going the "standard web browser way" and just letting the user set an email (login) and password.
When the iOS device connects to the server (using HTTPS), it uses regular "basic authentication" to log in, and receives a cookie which is valid for a set period of time. As long as the device keeps requesting data from the server within the cookie's lifetime, the cookie is renewed, and when the cookie is expired the server will automatically challenge the client to log in using its stored information again.
This has some advantages;
The user can log back into his account with a new device with a regular password reset. Easy, straight forward solved problem.
There is no special solution on the server side, any server side script can require authentication just like it would for a browser - built in functionality.
You would not have to invent your own security scheme. This scheme is used by millions of browsers every day to authenticate to web sites.
Not tied to a special phone, if the user has several iOS devices, he can use the same account from all of them by just logging in. No special set up procedures.
In other words; no special solutions for you to develop, generally solved problems how to handle login information, proven security and ease of use.
According to me, you can't really beat that :)

Resources