Stop concurrent multiple client's access to the ASP.NET Web API and ASP.NET Identity 2.1 - asp.net

Problem statement:
Hi. I have some secured data which I want to expose through Web API and ASP.NET Identity mechanism. I want to use out of the box classes of ASP.NET Identity. I take a payment manually and change a value in the table. But there are cases where the user will share his username + password with some other guys so that the others can access the same content without paying anything.
Work plan:
So, I have extended the AspNetUsers table with a column named ApplicationToken (varchar). After successful login, I want to generate a token, update the field of the user's row in the table, and add this value as a claim information and send back to the client app. Now, when the user requests for a paid content, my client app will send the token also. So, somewhere in my server side codes, I need to check this ApplicationToken with the Database token value. If both are equal, I allow the request to proceed, otherwise I will send 401 Unauthorized and tell them to login again.
Implementation options:
After studying and searching, I found the below options to implement:
Create Custom Authentication Filter attribute so that I can grab the claims send from the client and do my required validation
Create a base class of the secured API and get the claims there and do my required validation.
Go for different Jwt based implementation where I should have access in both issuing and checking the Json Web Tokens.
If you have any other options, I would be very glad to hear those.
My question is, which approach is better to proceed. I have enough time to implement, so time is not a factor here. Thanks.

Related

ASP.Net Core 2(.1.2) - Save user data without having to trust the client

I'm currently working with ASP.Net Core 2.1.2 and I can't find a solution for my problem.
Currently I'm building a controlpanel together with Angular 5.
The data for a user is stored in a MySQL database.
To have access to the controlpanel you have to login - and the server will load some data. Important is the admin-level (1-?) - some actions are only allowed for admins with atleast a level.
For the authentication I'm using JWTBearer, which gets sent by the client at every HTTP action as header. But in some methods I also want to check the admin-level.
Now where can I store data for the client, like his admin-level?
Is it safe to save it with a Claim? But then wouldn't it be possible for the client to modify it clientside and send a "custom" header?
I also tried to put the data in a dictionary and use the (HttpContext.)User (of type ClaimsPrinciple) as the key, but that won't work because User is always different at every Request.
Is there any safe way to store the data for a User?
You can safely store your admin-level information in a Claim, unless you're worried that someone can read it. It's not possible to modify a Claim in JWT, because its value is signed by key which only you should know and after the modification this token will be invalid. Read this article to get more information about JWT

Persist user security profile data at custom Claims

My application have to fetch data from external services with the usage of manually provided at profile/management by user api key & api secret.
I'd like to prevent a huge amount of retriving those necessary keys queries to database and persist it somewhere else (assuming that those keys won't be updated too frequently).
From my point of view it could be implemented with next options:
Use MemoryCache provider with SlidingExpiration;
Create a custom Claim and append it into existing Identity claims collection;
Please correct me if I'm wrong, but if I've realized it right - claim's information is a part of data, which is used for serialization/deserialization at frontend<->backend interaction (I'm not quite confident about it, but suppose that it's used within cookies & tokens).
Actually these keys are also required for a several background processes (message queue consumers or scheduled jobs for example).
Would you mind letting me know a proper way for persiting such protected and frequently used fields in an optimized way?
Thank you in advance.
When you login using one of SignInManager's sign-in methods, it sets a cookie on the browser with an access token in it. This cookie contains claims data. So in subsequent authorized requests, you can query the User.Claims field to access the required fields without making a trip to your datastore.
Now whether you choose to use claims or not totally depends on how often you need the API Key / Secret. Your claims are part of the access token. If sending the API key / Secret on every request is justified, claims is the ideal choice.
UPDATE:
Rather than decrypting the tokens at the frontend, it's better to send them to the frontend client along with the access token.
Incase you're not aware of IdentityServer4 or OpenIddict do check them out. It's probably got all that you need.

Google OAuth Always Showing Consent Screen

I'm building an installed application that will have features requiring the Google Drive REST API using Qt and C++. I understand Qt is now releasing new libraries to support OAuth flows but let's assume I'm a student and learning to use OAuth at this layer is a requirement for this project.
In my application, I have a working OAuth flow for installed applications that ends with an Access Token and Refresh Token being stored using QSettings (I'm open to input on whether this is a disastrously bad idea too). The application requires no authentication/login for its own sake/data, but it does need authentication to Google for calling API's using an Access Token. This application has no associated web backend being hosted; its simple and should be deployable completely locally (I've written and included a simple TCP server that will receive the authorization redirect_uri and will run and close when called from within the application).
As such, I'm curious about the best way to make sure that, when a user opens my application and wants to use the Google Drive features, they are appropriately authenticated on Google's end. Say, if I maintain an access token in the registry, and this access token is granted per-user/per-application basis (right?), then how can I make sure only the user the token belongs to is able to make calls to the API with it?
Here's my understanding and approach; feel free to correct me or educate me if I've got the wrong interpretation.
If an Access Token is found, perform the following:
Open a browser page to a Google login domain and have the user authenticate there (this could prohibit a user from being able to use a cached login session that would have access to a token they otherwise shouldn't have access to)
If user has correctly authenticated with a Google account, return control to the application and make a test call to an API using the stored token.
If the call fails (responds with an invalid_credentials) I should be able to be sure its because the access token has expired and the application will go through the flow to renew an Access Token from a Refresh Token.
If no Access Token is initially found:
Start a normal OAuth installed application flow
Get the tokens and store them so that when the user opens the application next time the former procedure is used
My issue then is the first two steps if the Access Token is found. Nominally this could be done by the typical OAuth flow but it appears that when using a localhost as the redirect uri, Google will always prompt for consent, regardless of settings for prompt and access_type authorization query parameters.
What can be done to accomplish these first two steps in a way that my application can control (i.e. not a solution that relies on a backend server being hosted somewhere)?
If this question is too open-ended for SO requirements I can make some more restrictions/assumptions to limit the problem domain but I'd rather not do that yet in case I unknowingly rope off a good viable solution.
Thanks for reading! Sorry if its a verbose; I wanted to ensure my problem domain was fully fleshed out!
If you are using an installed application, I wouldn't recommend using or storing refresh tokens. Storing refresh tokens on the client side means that if an intruder gains access to the client's application, they have infinite access to the user's application without ever having to enter the user's credentials. If you do insist on having a refresh token, ensure you follow the Google's installed app flow, with the code_verifier parameter included in your requests.
If the access token is found, you should try to verify it, and if verified then use it at the google api, otherwise force the user to login again (or refresh it if you chose to still use refresh tokens).
If no access token is found, your flow sounds fine.
A few notes on loggin in with Google:
Google will only return a refresh token if you specify access_type=offline in your auth request.
Google will only return a refresh token on the user's first authorization request, unless you always specify prompt=consent in your query params.
In my experience, when leaving out the prompt query param, the user is not prompted for their consent again. If they are logged in to google, you will get a new access token, but no refresh token, unless you have prompt=consent.
I think the idea is you use prompt=consent if you have no record of the user ever using your application. Otherwise if they have used it before, you may prefer to use prompt=select_account to allow the user to select which account he wants to use in case he has more then one, or you can just use prompt=none.
This is just my understanding of it all.
My approach I ended up using was just to deploy with an SQLite db that will be stored in the AppData roaming directory. The db schema includes a field for the user's Name (from the OpenID IDToken field if it exists), the user's picture URL (again from IDToken if it exists), the refresh and access token strings (will be stored as encrypted strings when I get around to it), the user's UID/sub string, and a field for a user name and password.
These latter two fields are authentication fields for within my own application, which, again, I wanted to avoid but it seems impossible to do so. So the user will be prompted to enter a username and password into a form, and these credentials will be checked against the existing SQLite db file mentioned previously.
If they exist and are correct, the user gets logged in and will have access to their respective access and refresh token.
If the user has forgotten their password, they'll be asked for reconsent (going through the installed app flow again), and whatever password they provided during initial login will be used as the reset password. It is considered, for my purposes, that logging into Google for the installed app flow is proof enough that the user account belongs to them and they should have authorization to reset the password.
If the user is a new user and doesn't have a record in the local SQLite db file, then they can also click a button to "Create New Account" - which effectively goes through the authorization flow as well but this time a whole new record is posted to the SQLite db with the appropriate fields filled.
There's still more optimization that could be done but at least I am getting closer to the level of security and control of access to Google user accounts that I want.
I'm not marking this as an answer because I feel like this solution is still not desired and that there should be an easier way. So if someone has evidence or experience of providing an equivalent level of authentication control without needing to maintain a local user account database then I would be more than happy to mark such a method as the solution!
Thanks again!

Not handling authentication, but need claims and cookie

I am creating a new asp.net MVC 5 application. Authentication is handled by a third party using smart cards. Once a user is authenticated by the third party, I am sent the user's unique ID (inside the http header) which I match up against my database in order to find relevant information about said user (roles, display name, etc.).
Currently, on every page request, the sent user ID is compared against the database, and checks are performed to ensure the user has the proper permissions to view the requested page. While this works, it sure seems like a bunch of needless database hits when all the user information could just be stored in a cookie.
If I was using Individual User Accounts for authentication, what I am looking to do would simply be built in using Identity and OWIN. But since I am not handling the authentication, but merely the authorization, is there a way to use all the nice features of Identity and OWIN (claims and cookies specifically)? If not, how might one go about this?
Also, of particular interest to me is when a role is added or removed. Using OWIN with Individual User Accounts, updating the cookie is as simple as logging the user out, and then back in immediately in the background. That functionality would also be desired for any solution presented.
Any insight would be extremely helpful. Thanks for reading!
You could do what you're asking by directly storing values in a custom cookie, but for your purposes it sounds to me like you might be more interested in utilizing sessions to track that info. This will keep all of your actual data stored server-side, which is more secure as it isn't vulnerable to cookie modification and it allows you more freedom to control the state (for your role example, you wouldn't have to "update" the cookie at all, just update the session variable on the server side to add or remove the role as needed).
Figured it out. Found a great article that really helped:
http://www.khalidabuhakmeh.com/asp-net-mvc-5-authentication-breakdown-part-deux

Track OAuth 2 provider on client page

I have the ability to login via Facebook and Google on my website. This is done using OAuth2.
I use the same redirect URL whether the user is returning from facebook or google, and pass through the provider name in the state field. Is this the recommended way to track the provider? Otherwise I do not know who to validate the token with if I do not know which provider the token comes from.
Are there other preferred methods for accomplishing this?
The state parameter should be an opaque value that cannot be guessed by an attacker since it is not protected from modifications. If you need to track state, you should refer to it by using the state parameter but that parameter itself should be randomized and/or encrypted. Storing the provider identifier in plaintext in the state parameter is not safe. Users could modify the state parameter themselves or attackers could craft an authorization request with a state value that they choose.
The way to track the provider is by storing it in the backend session state and generate a reference to that session/state that you pass in the state parameter. To prevent cross-site request forgery you should also keep some encrypted/randomized cookie that binds the state to the browser. This is described in more detail: https://www.rfc-editor.org/rfc/rfc6749#section-10.12
Addendum:
One of the problems with using OAuth 2.0 + provider specific extensions for login is exactly this: you cannot establish the provider and user identity in a way that works for all providers in a uniform and generic way. In your case you'll already have to know the provider before you can perform a sensible interaction with it. Enter OpenID Connect: it is a extension profile of OAuth 2.0 that gives you login semantics in a standardized way. It would give you a verifiable JSON object (JWT) with standardized values that tell you who the provider is (iss) and who the user is (sub).
Google signin already has migrated already to OpenID Connect, as has Microsoft and others like Salesforce, hopefully Facebook will follow.

Resources