Persist user security profile data at custom Claims - asp.net

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.

Related

Managing Session Cookies, from Firebase Authentication, with Redis

I am using Google Firebase Authentication to handle user management for my web application.
Specifically, I am using managed session cookies. The problem I am running into is figuring out how to associate each session with a corresponding user.
For example, I would have two separate tables:
User - Stores personal information such as name, email, password, etc
Account - Stores account related information such as posts, friends, etc
I was thinking of using Redis as a key-value store for this situation and the flow would work something along the lines of this:
User enters credentials
Credentials gets verified by Google's backend
User receives ID token
User sends ID token to my backend along with user id
Google's backend creates a session cookie
Backend would store the session along with the user id into Redis
Whenever user hits a protected endpoint that requires user id, a call to Redis would be made
I thought this might work because, within my Flask API, if I print out the type of the session cookie, the value is of type string.
I was wondering if this is an overkill, or if there is a better alternative to achieve what I want.
After much research and discussions with peers who work in the software industry, I have decided to use the strategy outlined in the question.
Feel free to comment if you have anything else to add.
Cheers.

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

asp.net core identity claims vs properties (efficiency point of view)

i've read all the tutorials and questions asked about the subject but they contradict one another
claims(userclaims and roleclaims) are serialised into a cookie (along with custom identity user properties you specify by overriding the principle factory) but they don't get queried, they're stored in a cookie, which mean that the more claims a user have, the more data will have to round trip between the server and browser
a custom identity user property by default don't get serialised but get queried from the database, so every time you need that data it query it from the database which is more work to do on the database on each request if you frequently query for it
so which is more efficient and which is safer
for instance
IsAdmin should be a role/claim? but then if someone stole the cookie, nah nah, the cookie already contains userid/username/securitystamp, so even if it's a property, the userid on the stolen cookie would query on the custom identity user property, or is there something that will prevent this cookie from working when stolen ?
another instance
if i've 20 property for the user (first name, last name, address 1, address 2, postal code, whatever the case may be), should i simply have the user wait a bit for a bigger slower cookie to be send back and forth or should i do all the work from the db using custom identity user
but then, if i remove or add a claim to the user, would it be updated on the next request if it doesn't get queried or is the security stamp validate that this cookie is still valid ?
cause at the Task AddClaimsAsync of the userstore of efcore it only add the claim to the dbset
i apologize i know this is many questions to ask but the resources on the matter are not that good and one can easily get lost reading the identity source
Rule of thumb - put frequently added items as a claim, everything else can live in DB and be queried on demand. I.e. address 1, address 2 can't be required on every request, so keep them in the DB.
On the other hand IsAdmin (should be a role anyway) I can imagine will be checked on every request, so it should be in the cookie without having to query the db.
If you afraid of your cookies getting stolen, don't show them to anyone! set up SecurityStampValidator to do frequent checks - like every 5 minutes. This basically updates the cookie with the fresh information from your database and changes the cookie. So even if the cookie is stolen, it will only work for 5 minutes.
I don't think the two statements contradict, it depends on your configuration. The second statement mentions "by default".
You do not need to store all information in claims nor do you need all the information all the time. If you want profile information, call the server once and store the information on the client, or get it when needed only.
The same counts for authorization, in case you want to show / hide elements based on permissions. This may include a tag called "IsAdmin". Authorization should be kept close to the resource.
If your client wants to refresh the information, just call the server. Claims are not updated during each request. In general, the user has to log out and log in again. So Claims are not flexible and therefor not really suitable for properties that can change (frequently).
As for safety, it doesn't really matter that the client can alter the information, it is for display only. It doesn't change the permission in the backend.
You can consider to add something like a display name to the properties, if you are showing that in every page. You can also consider to implement caching to limit database calls. In the end it really depends on your requirements.
As for stolen cookie, you'll need to implement additional security to your server to detect suspicious behaviour. You may want to include the ip address as claim. As for the admin, add security, e.g. filter by ip address and / or use an additional code which was send by email.

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

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.

SignalR on ASP.NET MVC and Multiple User Types

I am currently in the process of sketching-out an application that allows real-time interactions with website visitors.
Therefore, I have two different "User-types":
Unregistered User: these are the visitors
Registered User: these have a (custom) ASP.NET MVC membership
Now, I am persisting "UserNames" and ConnectionIds in a DB so I can freely scale at some point in the future. I do this by accessing Context.Identiy.User.UserName from within the Hub and then query the DB for any existing "sessions".
Here is the problem:
I need two different types of "User"
For one, I want to dynamically generate a GUID - these are the visitors and will be removed from the database after a given amount of inactivity.
These are the admins, they have their proper identities attached to the Context object.
So, how would one go about accessing a "session" from SignalR? It is not really a Session, I just need to get a SessionId from a Cookie on each initial request to the MVC-Controller, that's all. All I need to be able to do is:
Have an auto-generated "SessionId" which I can use to persist visitors across requests
Have a more "extended" identity: I want to use UserId instead of UserName
Anyway, I hope this makes sense but chip in if anything is unclear.
Okay, I just realised that I can use "HttpContext.Current.Request.AnonymousId" and I am linking this up to a Session-database.
Here some relevant documentation: http://msdn.microsoft.com/en-us/library/system.web.httprequest.anonymousid.aspx
This solved my problem in this case. :-)

Resources