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
Related
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()))
}
}
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.
I am integration Salesforce OAuth in my application. After mapping users' Salesforce account with our application account I saved access token in DB. When user make request to fetch data from his Salesforce account I just use that token to get data. Sadly, token has expiration time (max 24 hrs). After token is expired user has to again connect salesforce account with our app.
Is there anyway to keep salesforce session alive for unlimited time or any other way to avoid repeated login?
I think what you are looking for is a Refresh Token process. Although you can control the expiration time, as you said there is certain limits you can't pass. Instead you can send a request to your org that can obtain new Session ID for you.
Example:
POST /services/oauth2/token HTTP/1.1
Host: https://login.salesforce.com/
grant_type=refresh_token&client_id=3MVG9lKcPoNINVBIPJjdw1J9LLM82HnFVVX19KY1uA5mu0
QqEWhqKpoW3svG3XHrXDiCQjK1mdgAvhCscA9GE&client_secret=1955279925675241571
&refresh_token=***your token here***
Note that this does not work if you are using username-password OAuth authentication flow. Check this dev documentation for the parameters you can use for Refresh Tokens and what responses can it return. - https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_refresh_token_oauth.htm
It is not possible to make sure that user session never expires. However, you can setup the session timeout value to a maximum of 24 hours.
I agree with Iojo. I implemented the similar requirement to save the Token in DB and reused it for multiple API callouts.
Note: In my case - for all the API callouts - Authentication layer are taken care by same middleware. Additionally, I am using username-password for access token where, clearly, I cannot use refresh token.
What I did for Access Token with token
saved in DB?
//Please create a re-usable method in the Rest handler to Retrieve Token
private string getToken(){
If(Token created within Session Timeout Limit){
//Use encrypted token given in the DB
}
else{
//reuse code to generate new token
//save the encrypted token in the DB for future use
}
}
Benefits:
You need to generate Token just one time within given Session Timeout Limit
Re-use the same if there are multiple API calls in salesforce
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
I'm implementing my own OAuth authentication system (with refresh_token support) for an app and I have some questions about how to do it:
Client identification: The client is registered in the auth server and gets a client_id and a client_secret. How do I generate it? is there some kind of relation between both values?.
User authentication: The client sends the users_credentials (username+password for example) + client_id and gets a refresh_token and (temp?)access_token. That access_token is the one I should use in further request or I should use a accesss_token`=F(refresh_token,access_token,client_secret). In the second case what does the F function consist on?
Access token refresh: The client send client_id, refresh_token and gets a access_token (and a optional new refresh_token). Does the access_token need the same conversion (whatever it be), as in the point 2?
If I'm wrong, when and how is the client_secret used?
Complete answers and concrete examples will be "bountied".
The authorisation/authentication server generates these values when you create an account with them (for instance when you create a developer account with Facebook or Google). If you are doing these parts yourself, they should be cryptographically secure pseudo-random numbers or letters. Remember that the client ID is usually publically visible, so choose a reasonably large set of alpha-numerics (I use 30 characters). The secret is private and can be harder to guess so I chose 30 digits with letters, numbers and symbols. These are not related to each other, it is just that one is public and the other isn't.
The usual way this works is that there is a browser redirect to the auth server passing the client id in the URL (and redirect uri) and specifically NOT the user id and password. The whole point of OAuth2 is that the client system never sees the user name and password, only the auth server. After this redirect, the auth server verifies the client id, checks the username/password (for instance) and then returns to the redirect uri with a temporary code. This temporary code is passed back to the Auth server in order to obtain an access token. Since this call is made as a POST from the server, it also passes the client secret to verify that it really is the correct client system and not someone who stole the client id from somewhere else. At this point, the auth server will return an access token (and optional refresh token - you do not need to use them, I don't).
If the client system wants to log the user in without them having to type in their username and password all the time, it can use a refresh token, if available, to call back onto the Auth server and if the Auth server is happy that the refresh token is still valid and any other business rules are correct, it can give you back another access token directly without the user being involved.
I recommend reading the OAuth2 spec here: OAuth2 Spec RFC6749. It can take a while but if you delete the bits you don't need and reduce the amount of data, there are plenty of useful examples in it.
FIRSTLY, The client identifier can be any string that you want, but it should be unique for each client. It can even be the client's choice if you wish.
The client secret should be a cryptographically strong random string. Here is how you could generate one in C#:
RandomNumberGenerator cryptoRandomDataGenerator = new RNGCryptoServiceProvider();
byte[] buffer = new byte[length];
cryptoRandomDataGenerator.GetBytes(buffer);
string uniq = Convert.ToBase64String(buffer);
return uniq;
SECONDLY, The whole point of OAuth is to allow external apps to do things on your behalf without asking for your credentials. So, you need to implement an authentication server that does the logging in part for you. The user opens the app and gets an option to Log in using your website. You tend out access tokens and refresh tokens once the user has keyed in his credentials. The app can then simply use the tokens to perform actions on the user's behalf. I wrote an answer to How would an efficient OAuth2.0 server / provider work? that explains how access tokens can be constructed.
Remember, the need for refresh tokens and the lifetime of access tokens purely depends on how you intend to use them and what does your security framework look like.
LASTLY, The refresh token can also be an HMAC encoded string/a JSON object as I had explained in the answer to the linked question. You can have random refresh tokens and a large backend storage to keep it to verify the tokens in the incoming requests, or have HMAC encoded strings for added security/less storage requirements/latency to decrypt/encrypt tokens.
Also, do make sure that you go through all the flows and possibly the RFC too as mentioned by Lukos.