How does Identity.GetUserId() finds the user Id? - asp.net

Question
How does User.Identity.GetUserId() finds the current user's Id?
Does it find the user Id from the Cookies, or does it query the database? Or any other methods?
Problem
For some reason, User.Identity.GetUserId() returns null when I add a valid Bearer Token to my Http request header and send the request to my controller's endpoint:
// MVC Controller Action Method
[Authorize]
public HttpResponseMessage(UserInfoViewModel model)
{
// Request passes the Authorization filter since a valid oauth token
// is attached to the request header.
string userId = User.Identity.GetUserId();
// However, userId is null!
// Other stuff...
}

How does User.Identity.GetUserId() finds the current user's Id?
ClaimTypes.NameIdentifier is the claim used by the function User.Identity.GetUserId()
You would need to add the claim in your authorization code,
identity.AddClaim(ClaimTypes.NameIdentifier, user.Id);
identity is of type ClaimIdentity.

When the user is logged into your app, the server, using ASP.NET Identity, validates your user using DB and creates a valid token that returns to the UI. This token will be valid to its expiration and has inside all information needed to authenticate and authorize the user, including the user's Id. Next calls from client side to server side must be done using this token in the http request header, but server will not call the DB again, because ASP.NET identity knows how to decrypt the token and get all the information of your user.
The use of cookies is only a way to store the token in the client side. As I commented above, you have to send the token on the next requests after the login, so you can store this token in cookies or in Session Storage in your browser.

First, make sure you're not allowing for non-authenticated users.
After that, you want to parse Bearer tokens you have to configure it.
You're going to the need this package Microsoft.Owin.Security.OAuth
And at startup if have to configure ASP.NET Identity to use Bearer Authentication with:
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions {
// your options;
});
Probably on your StartupAuth.cs file

Related

How is this access token stored on the client, in FastAPI's tutorial "Simple OAuth2 with Password and Bearer"

I'm pretty new to FastAPI and OAuth2 in general. I just worked through the tutorial "Simple OAuth2 with Password and Bearer" and it mostly made sense, but there was one step that felt like magic to me..
How does the access token get stored onto the client and subsequently get passed into the client's requests?
My understanding of the flow is that it's basically
User authenticates with their username and password (these get POST'ed to the /token endpoint).
User's credentials are validated, and the /token endpoint returns the access token (johndoe) inside some JSON. (This is how the user receives his access token)
???
User make a subsequent request to a private endpoint, like GET /users/me. The user's request includes the header Authorization: Bearer johndoe. (I don't think the docs mention this, but it's what I've gathered from inspecting the request in Chrome Developer Tools)
The authorization token is then used to lookup the user who made the request in (4)
Step (3) is the part that I don't understand. How does the access token seemingly get stored on the client, and then passed as a header into the next request?
Demo
When you run the code in the tutorial, you get the following swagger docs. (Note the Authorize button.)
I click Authorize and enter my credentials. (username: johndoe, password: secret)
And now I can access the /users/me endpoint.
Notice how the header Authorization: Bearer johndoe was automagically included in my request.
Last notes:
I've checked my cookies, session storage, and local storage and all are empty
The authorization header disappears if I refresh the page or open a new tab
I suspect Swagger is doing something under the hood here, but I can't put my finger on it.
If you need persistence for the token you'd usually use localStorage or similar, but in SwaggerUIs specific case, the authentication information is kept internally in the library.
If you have enabled persistence SwaggerUI will persistent the access token to localStorage:
export const persistAuthorizationIfNeeded = () => ( { authSelectors, getConfigs } ) => {
const configs = getConfigs()
if (configs.persistAuthorization)
{
const authorized = authSelectors.authorized()
localStorage.setItem("authorized", JSON.stringify(authorized.toJS()))
}
}

Firebase auth idTokens

I have read so many articles about firebase auth on web but couldn't find any clear explanation of how idTokens are supposed to be used on the client side. Here is what I know so far
After the user has logged in, we can get the token using the following method and it will automatically refresh the token if it has expired
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
// Send token to your backend via HTTPS
// ...
}).catch(function(error) {
// Handle error
});
We can then send this token to our backend where we can use firebase admin SDK to verify the id token and get the user uid.
admin.auth().verifyIdToken(idToken).then(function(decodedToken) {
var uid = decodedToken.uid;
// ...
}).catch(function(error) {
// Handle error
});
Here are the things which I don't understand.
Do I need to call getIdToken() method before each API call to the server to get the idToken?
Firebase documentation says that the token expires after 1 hour. So am I supposed to keep a track of that using localStorage and then reuse the token for 1 hour till it expires and then issue a new one using getIdToken()?
Should I instead create a session on the backend with the uid which won't expire and then use that to verify if the user has logged in or not?
No; as you noted, the token is valid for an hour. You can reuse the same token during that period unless you have a reason to refresh it (for example, if you add custom claims)
Ideally your server will return a 401 Unauthorized or something when the token is invalid. Most REST libraries provide the ability to add interceptors in the request chain, so you can check if you get back a 401 code and only refresh the token when necessary.
There is no need for a backend session unless your business logic requires it. The Firebase library will handle persistence for you.

Get the refresh token from the PersistedGrantStore key property in identityserver4

I have already implemented my own IPersistedGrantStore called PostgresPersistedGrantStore that stores grant in my postgresql database and it works really great.
Now i want to move really forward and i want to get the refresh token from the key that is stored in my postgresql table. But from what i read it is not a proper refreshtoken but a hash to protect the refreshtoken. Is there a way to decrypt, read the refresh token from the key property, using maybe a fuction from the identityserver api?
I am trying to implement my own impersonation workflow, so it would be easy to login as any user using the latest refresh token that exists persisted in my db
A long time has passed since the question had been asked, but I think I'm sharing a relevant information.
Here is the method which is implemented at IdentityServer4.Stores.DefaultGrantStore<T> and actually creates the key for the refresh token.
protected virtual string GetHashedKey(string value)
{
return (value + KeySeparator + GrantType).Sha256();
}
Where
value is the actual value of the refresh token,
KeySeparator is a
constant string field defined at the same class, the
value is ":",
GrantType is 'refresh_token' in this particular case.
This method is being used while creating/validating the refresh token.
I think this information clearly states that there is no way to get the refresh token value by using the key.
Reference:
https://github.com/IdentityServer/IdentityServer4/blob/main/src/IdentityServer4/src/Stores/Default/DefaultGrantStore.cs#L77
Identity Server 4 has a build-in endpoint for this - <server_url>/Connect/Token.
You need to send a POST request to this endpoint, with x-www-form-urlencoded body type, which contains:
refresh_token: current refresh_token
client_id: the client that you are refreshing the token for
client_secret: the secret of the client
grant_type: refresh_token
It will give you back a "refreshed" access_token along with a new refresh_token.
The initial refresh_token you should have received once you have logged in. Have in mind - once refresh_token is used (to get a new access_token) it gets invalidated. This is why you are receiving a new with every request to the endpoint.
Here is some more info about the refresh_token itself.
And here - about the token endpoint.

Handling logging into SPA application: getting user info, managing claims

Context:
I've implemented OpenIddict in my application, basing on GitHub readme. I currently use TokenEndpoint to log user in.
services.AddOpenIddict<ApplicationUser, UsersDbContext>().EnableTokenEndpoint("/api/Account/Login")
Although calling /api/Account/Info works and it returns token in response, I need to get some basic data about logged in user (username, email, account type). Response from token endpoint doesn't provide that.
I've found something like UserinfoEndpoint:
.EnableUserinfoEndpoint("/api/Account/Info")
But what I see after in http response is:
{
"sub": "ea2248b4-a[...]70757de60fd",
"iss": "http://localhost:59381/"
}
This should return me some Claims. As it doesn't return anything, I assume that no Identity Claims were created during token generation.
What I need to know in a nutshell:
Is using Token Endpoint correct way to log in user?
Do I need to generate Claims by myself?
Can I control Claims by myself and how?
How to make some Claims visible through UserInfoEndpoint?
Is using Token Endpoint correct way to log in user?
Yep.
Do I need to generate Claims by myself?
The userinfo endpoint simply exposes the tokens stored in the access token (which is something that may change in the future).
Can I control Claims by myself and how?
How to make some Claims visible through UserInfoEndpoint?
To allow the userinfo endpoint to return more claims, you'll have to request more scopes. Read http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for more information.
In a future version, we may allow you to return custom claims, but it's not currently supported.

Pass auth token to wcf one time

I just started to work on wcf service build an web application to consume my service . I made that token based i pass token in every request and then check that token on each request from database that its valid or not . I think this is not good to send an extra request to db every time . So , is this possible to authenticate user first time when he login or first make request to service and after that until session remain all my requests work with token ?
I searched on google but every one was telling how to authenticate with service .
Instead of a random string that you generate and need to check in the database, make your tokens around encryption and/or signing just like many authentication modules do.
In other words, build a token from a user/application name, issue date and/or expiry date, encrypt it and you have a self-contained token that doesn't need any database lookups for validation.
For easy encryption, the MachineKey can be used
http://msdn.microsoft.com/en-us/library/system.web.security.machinekey%28v=vs.110%29.aspx
A side note - this is how forms authentication / session authentication modules work. You have cookies (tokens) that carry the authentication information. You could consider switching to these.
Edit: an example you ask about:
// create token
string username = "foo";
string token = Convert.ToBase64String( MachineKey.Protect(
Encoding.UTF8.GetBytes( username ) ) );
// get username out of token
string token = ....;
string username = Encoding.UTF8.GetString( MachineKey.Unprotect(
Convert.FromBase64String( token ) ) );
Checking the Auth token with the database on each request is probably a bad idea. What is commonly used as a token is the current user principal itself but serialized and encrypted.
The token is generated and returned to the client upon login. Then on each request you pass the token the service which then gives you the opportunity to deserialize it and populate your System.Threading.Thread.CurrentPrincipal without a roundtrip to the DB.
Check these SO answers for more insight
Delivering a JWT SecurityToken to a WCF client
How to use Microsoft JWT Token Handler to secure webHttpBinding based WCF service

Resources