I need to store a refresh token from OAuth securely, but I need it to be accessibly by my application for all users on the machine. From what I can tell node-keytar only supports credentials being stored on a per user account basis. Is there a way to securely store the refresh token?
For what it's worth, this is for an electron app.
Related
I'm trying to implement OAuth2 authentication for user through a powershell function app in Azure. Reading through the devops documentation, it specifically recommends persisting the refresh token on the app server:
Securely persist the refresh_token so your app doesn't need to prompt the user to authorize again. Access tokens expire relatively quickly and shouldn't be persisted.
What is the best practice for storing the refresh token? I can think of a number of ways but I'm afraid that I will do something naïve.
Storing access tokens poses a greater security risk, since an access token in and of itself can access resources. The recommended approach is not to store access tokens, but get the access tokens as needed. Securely store only the refresh tokens, with as much rigor as if they were access tokens. If necessary, you can revoke refresh tokens if they become compromised.
This solution uses Azure Key Vault, Azure Functions, and Azure DevOps to securely update and store OBO (OAuth 2.0 On-Behalf-Of (OBO) flow) refresh tokens.
More details you could refer to the following link:
https://learn.microsoft.com/en-us/azure/architecture/example-scenario/secrets/secure-refresh-tokens
I have an backend API in an Azure Website that I like to protect using Azure AD.
As I understand it I'll first do an App Registration, use information registration as part of the sign in to get a token back to the client.
I can then send that token to the API and validate the token in the backend API to verify it.
But don't that token give access to all resources in the subscription? How to I restrict the App Registration to only be allowed to access that specific API? And not also another API in the subscription?
I also like to have a set of users that are allowed to access the API. If I'll just allow everyone to log in using the App Registration, everyone that's in my AD will receive a token back?
Can I somehow use a Enterprise Application to restrict access to the API only and only allow a set of users?
Or is there another way of doing this?
But don't that token give access to all resources in the subscription? How to I restrict the App Registration to only be allowed to access that specific API? And not also another API in the subscription?
A token only gives access to the API identified by the audience (aud) claim in the token.
Nothing more.
So if your client app asks for an access token to your API, that token is only valid on that API.
I also like to have a set of users that are allowed to access the API. If I'll just allow everyone to log in using the App Registration, everyone that's in my AD will receive a token back?
Can I somehow use a Enterprise Application to restrict access to the API only and only allow a set of users?
Yes.
You can find the enterprise app (service principal) for the API, enable Require user assignment, and then assign the users/groups you want to have access to the API from Users/Groups tab of the enterprise app.
Access token acquisition will then fail for users who are not assigned.
If you are using the same app registration for both the client and API, then you have to remember that you should acquire an access token regardless to call the API.
Don't use the id token.
Also in that case, a user who is not assigned to the app will fail login.
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.
I am building an application that uses OAuth to authenticate and grant account access to users.
The current authentication flow is as follows:
Create new application
Register application with API service
Store granted client ID and client secret securely
Launch application
Application opens service's OAuth request for approval in SFSafariViewController
User approves the application to access their service's account
Callback to application provides code, which is received in AppDelegate
Notification is posted, passing the code to the view controller that will initiate the request to exchange a clientID, client secret, and code for an OAuth token to be used for authenticating subsequent requests
Send request with client ID, client secret, and code to exchange for OAuth token
Store token in Keychain for subsequent API requests
I have everything working as listed, however, I don't know how to store the client ID and client secret that I am granted when registering my application with the service. The client ID and client secret are to be kept securely and not shared. They will be used when a user exchanges them for an OAuth token.
Since I am using GitHub for version control, do I create a property list within my application to store the items? If so, I can just add that file to my .gitignore. Is this an appropriate method for storing my credentials?
You should not store a client secret inside a native app as it is a public client. Native apps are incapable of protecting data from the resource owner (and therefore a client secret).
Client secrets are intended for servers (or any confidential client) that are able to properly hide a client secret. You can standup a server (where the client secret can be stored) that handles the incoming requests from your mobile app over HTTPS, then sends back Access/Refresh tokens to your mobile app.
If I understood your question right (you need to store keys for each user), you may store them in iCloud containers. Basically it's like UserDefaults but in user's iCloud. You may write and read from there. Check out this docs for more info.
Let me know if it helps cuz not sure if I got your question the right way. If not please explain it in other way :) thanks
I want to provide a service using the facebook api to third parties. Is it possible for us to share access tokens? If the third party gives my service a user's access token, can I access that users data even if my app_id & secret do not match the app that requested it?
Should I have the users go through a separate oauth flow on my site even if they have already completed it for the other third party?
Thanks.
-ken
Even that user access token is issued only for one app it can be easily used from any other application.
Example:
Get access token for "Graph API Explorer" application here https://developers.facebook.com/tools/explorer/?method=GET&path=me and make a request - you will see your data.
Copy access token and open other machine|browser and go to https://graph.facebook.com/me?access_token=[access_token] - you still able to retrieve information about your Facebook user!
Here https://developers.facebook.com/docs/concepts/login/access-tokens-and-types/ it mentioned that
Our Data Policies explicitly prohibit any sharing of an Access Token for your app with any other app. However, we do allow developers to share Tokens between a native implementation and a server implementation of the same App (ie. using the same App ID) as long as the transfer takes place using HTTPS.
Regarding:
Is it possible for us to share access tokens?
and,
can I access that users data even if my app_id & secret do not match the app that requested it?
The answer is No. From the specs OAuth2 section 10.3:
Access token credentials (as well as any confidential access token attributes) MUST be kept confidential in transit and storage, and only shared among the authorization server, the resource servers the access token is valid for, and the client to whom the access token is issued.
Should I have the users go through a separate oauth flow on my site even if they have already completed it for the other third party?
The answer is Yes. If you're using facebook as authorization server, and you restart the oauth flow again, your user will only need to approve your other app (third party).
Each access token is issued only for one app - it cannot be used with different application IDs.