I'm building a native mobile app that connects to an OpenID authorization server using authorization code flow with PKCE.
As this is a native app, I would like to save the user credentials locally the first time the user enters the email and password. Every time the user starts the app, the app will start the login process using a browser instance in the background.
Is this a normal flow in native apps?
You should get some access token. In .net maui you can save it with SecureStorage.Default, which implements ISecureStorage interface. Read more here https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/storage/secure-storage?view=net-maui-7.0&tabs=android. You can ask for a new token occasionally and replace the old one.
If you are going to send user name and password each time, you might as well do it over non secure channel, and without hashing/encrypting the password.
The flow is like that:
You log-in and you save your token. (May be more than one)
You use this token for API calls. (Or different APIs)
At start, instead of generating new tokens, you use the saved ones.
You check if your token is expired or not. If it is expired - you make the user re-enter credentials.
If some token for some API returns 401 (Unauthorized) (Token has been revoked, for some reason) you make the user re-enter credentials.
If something is not clear, please ask.
Related
We currently have an Identity server 4 application. Using entity framework core and asp .net identity.
We have a group of supporters who need to be able to access our users accounts in order to help them with issues over the phone. Our users are not able to figure out how to use team viewer. As most of them are mobile and will only have a cellphone at the time.
I know all the security ramifications of allowing other people to sign into your account however there is really no way around this. Our customers have accepted that our supporters can connect to their account when they request it. We trust that our supporters only do this when its requested.
Current solution and its issues
The current hack creates an api endpoint which only our supporters can use as it has been locked down so that only those with supporter permission can use it. They send the users email and we hack create them an access token which is then used by the application (Web version) to act like its the user who is having issues.
This solution was created by my predecessor basically by taking the supporters access token and replacing all of the claims with this supporters id to the users id and returning it to the application. I hate this solution on a number of levels and its very unstable every time i look at this method it breaks. currently its not working because audience clams are incorrect for some reason.
What i want to do
I would really like to do this in a less hack way. So is there a way to sign in a user to the application without it actually being them thats doing the signing in and return an access token?
I have tried doing
await _signInManager.SignInAsync(user, false, null);
But i cant seam to figure out how to get that to return an access token.
What i would really like to do is have the ability for supporters to login to any ones account but do it securely somehow.
The problem with the user account is that it's not bound to one application. So by allowing others to login using the account, you give them also access to other applications. As a workaround you could use 'public' accounts, like engineer_01, engineer_02, etc.
But, this may not be necessary at all. What you really want IMO is to impersonate the user, instead of 'hacking' the account.
One way to do this, is to extend IdentityServer with a custom grant type using extension grants.
How this could work:
A signed-in user, who is allowed to impersonate users for the particular client/resource, requests an access token at the new impersonation endpoint.
The user sends the sub from the user to impersonate to the endpoint, where the user and (combination of ) sub are verified.
When access is granted a new (short-lived) access token is returned which can be used to impersonate the user, without having to know the credentials of the user.
The access token should contain information of the endpoint so it can be determined whether the user is impersonated.
We implemented an impersonation feature that is integrated into the browser-based sign in flow. If a user with permission chooses to sign in as another user then we add additional claims to their IDS4 authentication cookie which then supports issuing extra claims in the resulting token that reflect that it's an impersonation session and who the original actor is.
Navigate to client application
Sign in using whatever credentials
Check if any impersonation permissions exist (how these are defined is entirely up to you)
Prompt for impersonation account selection (or just continue as self)
Sign in as the selected account (with record of original actor)
Redirect to authorize endpoint
Issue tokens and redirect back to client application
A requirement is set upon me to implement impersonation for developers, of course only for development environment. I was wondering if it is possible to request a token for any AAD user without knowing the password. The flow I would want is:
Developer goes to web application to select a user he wants to impersonate.
The web application checks if the developer is in the AAD.
The web application checks if the developer has the necessary rights to impersonate.
The web application returns a token valid for the user the developer selected.
The developer can use this token to authenticate against the API, and for all intents and purposes is the impersonated user.
Any good alternatives to this approach are also welcome.
No, you cannot impersonate a user like this.
You can acquire an access token if you know their password and they don't have MFA etc. with the Resource Owner Password Credentials grant flow.
But if you want to do it in a better way, you could have the users who you wish to impersonate login to your app.
Acquire an access token + refresh token for them.
Then store the refresh token securely.
Now you can use the refresh token at any time along with your app's client credentials to acquire a token for that user.
Refresh tokens can and do expire though, for example if the user's password is changed.
But this could allow you to implement what you want.
I am developing an UWP app and the user is able to register/login. After a successfull login attempt the login information should be saved, so the application can relogin after every start.
Is it safe to save the information or should I modify my service so it works with tokens?
(If a bad guy can get the password, he also can get the token and can take over the user - is it still safer with tokens?)
Use Credential locker API: https://msdn.microsoft.com/en-us/library/windows/apps/mt270189.aspx
And deal with tokens instead of passwords for client-side.
I think that you can follow this implementation Username and Password data Windows phone 8 app
They use IsolatedStorage and Cryptography
Saving the user's credentials in the app is never a good idea. You should only ave the auth token / cookie / whatever the server issues after login and is required with the requests.
When saving the auth data, encrypt it using Windows.Security.Cryptography.DataProtection, sample here. Os use the Windows.Security.Credentials.PasswordVault.
Note: This is not about coding, but about the approach itself.
I'm making a client for a website which uses OAuth 2.. Since this is my first time using oauth 2 I have some problems in understanding the approach. As I know until now:
I should send my access token with every request. To get this access token in the first time I send user to the website and after login I get an authorization code. Then I send this authorization code and my client_id and client_secret to get the access token and finish.
until here every thing is fine. But in the next application execution, I don't know what to do. I don't want to ask user to login every time. But how can I know my access token is still valid?
should I save my authorization code and request a new access token again?
I request a non-expiring access token, but to refresh the access token I should send some refresh_token? What is this? Should I send the old access token as this?
#Eugenio's answer is correct.
To answer your specific questions
But how can I know my access token is still valid?
The access token comes with an expiration time, usually one hour. The other way is to try to use it and catch the 401 status if it's expired.
should I save my authorization code and request a new access token again?
No. The authorization code can only be used once. You can either request a refresh token, save that, and then use that to get subsequent access tokens, or you can repeat the authorization process, which depending on the provider, may or may not require user involvement since the provider will know that the user has previously authorized your app.
I request a non-expiring access token, but to refresh the access token I should send some refresh_token?
There is no such thing as a non-expiring access token. You use a refresh token in order to obtain a new access token.
What is this [refresh token]?
It's a string that your app can pass to the provider to say "hey it's me again. Remember a while ago user xxxxx, granted me, application yyyy (client id), the authority to do aaaa and bbbb (scopes) on his behalf, even when he's not present. Well I'd like to do some now so please can I have an access token".
Should I send the old access token as this?
No. Once an access token has expired it has no use or significance at all.
The access_token you get from the authentication site is good to call their APIs, not your app. You should keep it if you need to call them back eventually in your app.
For example, if your users are authenticating with Facebook, the access_token you get will be good to call Facebook's endpoints.
OAuth2 is in essence an authorization protocol: the user is granting you permission to access his/her information on their behalf.
A commonly used, and useful side effect of this process is to treat these users as "authenticated" because, presumably, you can only get an access_token from a legitimate user.
It is then up to your site to establish a session with them. You would do this exactly as you would if you were authenticating the user yourself, likely after you successfully retrieved the access_token using the code. (or sometimes after retrieving the user profile from the Authorization Server, another common technique).
You can browse a sample that does this on the .NET platform here: https://docs.auth0.com/aspnet-tutorial (this is configured to work with our own OAuth server, but the principles are generic).
The code this sample relies on is available here: https://github.com/auth0/auth0-aspnet
I want my web server code (invoked from ASP.NET MVC3 site's controller) to be able to save files to Dropbox account.
I have examined two out of three .Net/Dropbox libraries and all of them require a user to "authenticate" via web-redirect to Dropbox to get a token.
Examined libs are Spring.Social.Dropbox and DropNet.
Can this authentication and upload be done via purely .net code without messing with the user's browser? Can the acquired token be saved for later use? This is theoretical question, not about particular implementation.
This is a bit of a complicated subject. As far as I know Dropbox uses OAuth, which is an authentication and authorization protocol.
General process is this:
You create authorization request token
User gets redirected, authenticates and grants permissions to your app.
You trade the request token for an access token
You must save the access token because it is used to perform actions on the users behalf
Access tokens don't usually expire and only stop working if a user revokes your application permissions.
This means the user will have to authenticate and authorize your application at least once so you can get the access token and access token secret.
After that, you are pretty much free to perform actions on the users' behalf based on the permissions granted. You must specify the access token attained by the above-mentioned process in order to perform actions.
In short, get an access token, save it, use it for requests.
Does this clarify it a bit for you?