I want to know, what is the internal process to encrypt and decrypt a Bearer token used in OAuth2 and the code in Asp.Net Identity.
Once the server receives a token, it is able to retrieve the UserId, Roles, Claims and all properties inside it. So, how are Bearer tokens decrypted? What is encryption algorithm and the code used?
Where are you obtaining the token from? Tokens are seldom encrypted (sometimes they are), but they will always be encoded (and signed). OpenID (a protocol on top of OAuth2) uses JWT. OAuth2 (not OpenID) uses "opaque" tokens.
See http://jwt.io for libraries on decoding a JWT.
Here is a little Windows Forms tool that decrypts OAuth 2.0 Bearer tokens using MachineKeyDataProtector.
So if your app is hosted in IIS, then you can use the above tool.
OAuth 2.0 Bearertoken gets:
Serialized into binary format
MachineKey encrypted (DPAPI is used when app is self-hosted, etc.)
Base64 encoded
Here is a short answer, all I have time for. OAuthBearerTokenOptions contains the code needed to create the token. It must be configured in your owin startup.
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
Given that...
var ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
var currentUtc = new SystemClock().UtcNow;
ticket.Properties.IssuedUtc = currentUtc;
ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(expirationMinutes));
string accessToken = oAuthBearerAuthenticationOptions.AccessTokenFormat.Protect(ticket);
Related
I was reading article on JWT web token as an access token that is being response to the user. Some of it mention that the web token should be able to be decoded by the user.
Does it means that it is not a good practice to decrypt the entire web token? For example, I suppose to return following JWT web token to user where this piece of information can be decoded.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
However, I feel that I do not want to let user able to decode his/her access token, so I use another encryption algorithm to encrypt everything into another form as follow and pass back to user.
So, I would decrypt this new text when I'll get this access token in the server and decode it.
Is it recommended to do it this way if I do not wish to expose some of the value available in claim (such as user id) to the user? If not, what are the alternatives?
JWT (RFC7519) is just a compact way to safely transmit claims from an issuer to the audience over HTTP.
JWT can be:
signed (JWS - RFC7515)
encrypted (JWE - RFC7516)
signed then encrypted (this order is highly recommended). The whole JWS is the payload of the JWE
encrypted then signed.
It makes sense to encrypt a JWS if you want to keep sensitive information hidden from the bearer (client) or third parties.
The real questions are: does the audience support JWE? If yes, which algorithms are supported?
JWT are "signed" and therefore its contents are protected from tampering: you cannot change its contents without invalidating them.
You can optionally "encrypt" the contents and therefore turn them visible only to issuer (the entity creating the token) and the consumer (the entity that is destined to use its contents after verification).
There's a standard for that: JWE
A token contains user data and acts like a temp storage. It is not good to store sensitive data in a token.
At the first level, you should store the user name and maybe role or something like that. You should not include passwords, so it does not need to be encrypted.
Nevertheless, you can encrypt it if you want.
Yes, the best practice is use the JSON Web Encryption (JWE) RFC, the claims in the JWT after decode it are in plain text, so if the user lost the token, the sensitive information as email, username, access permissions can be visible and can be used as a the initial information of any attack.
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
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.
How to use access-token concept that is used in facebook.
1)Can we implement same concept in ASP.NET based web application?
2)Can we use this concept in adding security to access in webservice ASMX and WCF ?
After long time I have found the answer I have posted.
If I am wrong please review my answer.
1) In Facebook server flow authentication when user is successfully authenticated Facebook generates authorization code parameter name as code.
2)In second step using all this parameter authorization code with client _ secret ,client _ id , redirect _ uri , state call Webrequest or call service if success then response have two parameter accessToken ,expires _ in.
3) This accessToken is used for getting userinfo like firstname,lastname,birthday etc with specified scope.
And this is general scenario that is used with WCF and ASMX webservice by storing valid accessToken to safe place or further use.
1) Access token is just a hash from some parameters, e.g.:
MD5(userName, userMail, someSalt, someOtherStuff)
So you can implement it for sure the way you like it. But better if it contains some secret information that can be retrived only by current user
2) Yes you can. As social networks like facebook do it:
there's some application secret key that is known on a server side (where your service runs), and some signature that can be retrieved from facebook api for some app and user and some other information.
Your facebook app gets that signature, it can use it to make hashsum with other parameters like userLogin, application scores or w/e else. Sends it to server.
On a server side you generate signature same way as your appliaction do based on parameters. If signatures are same request is valid. If know - someone is trying to do dirty things :)
For my web app security I'm using FormsAuthentication / MembershipProvider with a non persistant cookie.
My application interacts with some web services, these also use the Membership providers.
User passwords are hashed in the database.
The problem is the person logged into application the web service needs to authenticate with the web service using his username and password every time a page is loaded. BUT once the user has logged in his password is not retreivable as it is hashed.
I was wondering if the password could be stored securley in the Authentication cookie so that the user can authenticate with the web service.
Or a better idea!
EDIT
I LIKE JOHNS IDEA BELOW BUT HAVE 4 COMMENTS ON THE MECHANICS THAT I WANT TO RESOLVE BEFORE GOING DOWN THAT ROUTE...
I agree with #John's answer that using throwaway token is better than storing the credentials.
For the token you could generate some random GUIDs and store it in the database.
As an alternative that does not require coordination between your ASP.NET application and the WCF service, you could send a signed document as token.
create an XML or JSON document with signed time, user name, and signer's name (ASP.NET app).
generate a hash of the above document.
sign the hash using asymmetric encryption (use private key).
All WCF has to do is validate the hash and the signature. So this does not involve hitting the same database. Using the signed time, you can expire the token in fixed time.
Edit: The idea is based on public-key cryptography (also known as asymmetric key algorithm, public/private key). If you encrypt something with a private key you can decrypt it back only using the corresponding public key; and if you encrypt something with a public key you can decrypt it only using the corresponding private key. See Implementing RSA in C# for how code would look like in C#. Why is this useful? Because we can use this to implement digital signatures. A digital signature is a way to prove that I and only I wrote something, and no one else.
Following the above mentioned step generates a signature. You first need to define a canonical form of "let this guy in" document. Usually an asymmetric key algorithm can't handle too big input, so you generate a hash out of it, and you encrypt the hash using your ASP.NET application's private key. The resulting signature can only be decrypted using you application's public key. Finally you can package all three components (original document, hash, and signature) into some format like XML or JSON and send it as token.
As an example, let's say you use JSON format for everything. First, the original "let this guy in document":
{"UserName":"Foo","SignedTime":"2009-07-09T00:00:00","Signer":"ASP.NET APP1"}
Next, you generate a SHA-1 hash of the above string, which is byte[] and encode it with modified Base64 encoding or something, which would look something like:
b2YgYW55IGNhcm5hbCBwbGVhc3VyZS4
The above is bogus string, the actual stuff may look longer. You then take the hash byte[] and encrypt it using RSA, which generates another byte[] so encode that too with modified Base64:
mxlIGdlbmVyYXRpb24gb2Yga25vd2xfo34
Finally, you make another JSON document to store all the above.
{"UserName":"Foo","SignedTime":"2009-07-09T00:00:00","Signer":"ASP.NET APP1","Hash":"b2YgYW55IGNhcm5hbCBwbGVhc3VyZS4","Signature":"mxlIGdlbmVyYXRpb24gb2Yga25vd2xfo34"}
The final JSON document becomes your passwordless token. Pass it to WCF service.
The WCF service takes the token, construct the original document by removing the hash and signature:
{"UserName":"Foo","SignedTime":"2009-07-09T00:00:00","Signer":"ASP.NET APP1"}
Follow the same algorithm to generate the hash and verify it's the same. Decrypt the Signature using the public key of the ASP.NET app and see if it becomes the hash. At this point, the document is verified to be signed by the signer. Check the current time and the signed time and see if the token is still valid. All you need is a way to distribute public keys between two code base, which could be loaded from XML.
The best practice would be to not require the user to authenticate with his username and password on every request.
Instead, on the first authentication, the web service should return some kind of authentication token. This is what should be stored somewhere. I would recommend storing it in Session state, rather than in the forms authentication ticket.
When the ticket from the web service expires, you might consider expiring the Forms Authentication ticket as well, which would cause the user to need to log in to your site again, providing username and password, which you would validate, and then use to authenticate to the web service again, storing the ticket from the web service, etc.
On the web application you set up the Authenticate event of the Login control to instantiate a new service proxy and set the username/password in the ClientCredentialsin the proxy.
Now when you make the call to the Service through the proxy WCF will pass these credentials through the secure channel to the service and use them for authentication.
Now you simply need to store the proxy in session and use it for future access to the service as it has the channel state and a private key.
protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e)
{
bool Authenticated = false;
try
{
MyServiceClient proxy = new MyServiceClient("MyServiceEndpoint");
proxy.ClientCredentials.UserName.UserName = LoginControl.UserName;
proxy.ClientCredentials.UserName.Password = LoginControl.Password;
//It doesn't really matter what is called or what it does because
//Membership Provider for the Service does the authentication.
string retval = proxy.login("Logging in");
//Now that channel is established the proxy needs to be kept
//since it contains the channel state which includes a private key
Session["MyServiceProxy"] = proxy;
Authenticated = true;
}
catch (Exception ex)
{
//Login Error...
}
e.Authenticated = Authenticated;
}