Thread safe token handling in .NET - c#

I have Web API.
Authorization is made via token from 3rd party API.
If request comes i check is token set -> if not, get it, set and use.
If response is 401 i need to try refresh token and then call API.
How to make it thread safe way and make other requests wait until failed one retries?
Request -> if token set -> use token, make request -> if response 401 -> try refresh token, make request one more time -> if failed, die.
All threads should use same token and not try to refresh it when some other thread already tries to do it.

Related

Identity Server 3 - invalid_grant - Refresh token already used

In our application, we periodically encounter a scenario where the user requests a new token at the same time when we're automatically refreshing the token in the background (via JS.)
Both requests are using the refresh token & hitting the token endpoint.
If the automatic request finishes first, the user-initiated request results in an error. This is because both requests are trying to use the same refresh token but since it can only be used once, it's consumed by the first request and the second request gets 400 Bad Request.
My question is: What's the best way to handle the 400 response for the second request? Ideally, I want to silently retry the request and the user should be none-the-wiser.
If this occurs, the ultimate fall-back has to be reauthenticating - IdentityServer is doing nothing wrong, the ball is in your court.
But - you should be able to make this situation impossible by synchronising the automatic token refresh and the user-driven token request. If the refresh token lives in your application in one place, then you can regulate access to it via some kind of lock/release mechanism.
This npm package looks like it'd do it: https://www.npmjs.com/package/lock
Alternatively you could synchronise calls on the server by subclassing the relevant IdentityServer component, and using a per-client lock there - but IdentityServer is already complicated, it would require many locks in one place, and it wouldn't be easily scalable to multiple server instances.

OAuth2 in memory token loss due to server application restart

I encountered this problem in test stage of my application. Client set expiration date of token for very long time (19 years or so), so we wouldn't request new token often during tests. But After a while it came out that token has already expired (after random time).
The problem was server application being restarted/updated, resulting in in-memory tokens lost and rendering my simple check for expires_in not working:
if (_currentToken.ExpirationDate < DateTime.Now.AddMinutes(1))
{
_currentToken = GetToken();
}
How would I secure such scenario? It might as well happen on production, but hopefully more rarely due to less application restarts and shorter token time. Unfortunately I don't have an access to server side authorization settings and tokens won't be persited in any storage.
I would like avoid calling some dummy action on server to check if it returns 401 unauthorized before every action.
IMO it's server side's responsibility to validate token and decide whether the request with token could access specific protected resources . So as #armagedescu suggested , just send the token when performing token request , server side will check the claims like expire time , issuer ... and also check the signature . If token is expired , it will return 401 status code , and the OAuth 2.0 bearer token spec adds error, error_description, and error_uri attributes to the WWW-Authenticate header for reporting additional error information :
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example",
error="invalid_token",
error_description="The access token expired"
Then on client side you can check the errors , and refresh access token to perform another token request .

Token authentication for Web API renewal

I’m writing a web api that will be called from a background service to fetch some data. After some research I decided to use a Json web token to achieve that but I’m still a bit confused regarding when a new token should be requested.
Let’s say I start up my service, I request a token, the token expires after 15 minutes, then after 20 minutes I make an api call with the expired token. I will get an unauthorized error or something.
My question is: How will the client know when to request a new token? Should it request a new one before every api call? Seems like I’m missing something. Maybe I should make the token permanent and store it in the database?
Thanks
The answer to this is slightly application specific, but the OAuth specification has a mechanism for "refresh tokens", which can be used to grant new "access tokens" (the token typically included on each API request), without having to send the user to the UI authentication process to have them re-authenticate. So, once you request an access token, you will receive a refresh token and an access token. This methodology allows access tokens to be used for much shorter time frames.
This can also be done without refresh tokens, but in those cases the access token timeout would likely be longer, and then you would request that the user re-authenticate through the usual OAuth UI process. Note that even when you do have refresh tokens, the refresh token can also be set to expire, in which would then require a user re-authentication through UI again.
In some API's you just make the API request as usual, and if you get a response that is defined by the API to be one that indicates the access token has expired, you can then issue an API call to refresh the token (or fully request a new one if that is expired, or you the API doesn't have refresh tokens), and then make the original API call again with the new access token.
The API can also have a response that includes the timeout or expiration date/time of the access token as well. Then, the client can avoid sending the initial API call first, and simply send the refresh token call first.
In implementing your API, you could likely use any of these methodologies.
Here's some general discussion on the OAuth spec website, to provide more depth:
https://www.oauth.com/oauth2-servers/making-authenticated-requests/
https://www.oauth.com/oauth2-servers/access-tokens/access-token-lifetime/
https://www.oauth.com/oauth2-servers/access-tokens/refreshing-access-tokens/
And also, here's an example from the Twitter API regarding response codes showing one of the access token expiration techniques (see the "Error Codes" section, under error code 89, which implies the token has expired and you need to get a new one):
https://developer.twitter.com/en/docs/basics/response-codes
Since your client is background service , you can use the Oauth2 Client Credential Flow . Your background service can request an access token using only its client credentials when the client is requesting access to the protected resources under its control.
With this flow , you does't need to care much about the token expires , if client sends an expired token to web api , web api validate the token and create token expires response to your service , your service check the status code/response , directly send a new token request to web api to get new access token , there is no need to use refresh token which uses in other flows .
The fact is that your harness should be prepared to request any token when getting an Unauthorized status code. What I do in test is to check the expiration datetime, if close enough I refresh or get a new token whatever applies to your Auth. Also when getting an unauthorized status code my code does a refresh once and keep a count. If I get another unauthorized code then I return a false or throw an exception after I log the error on the second try. This works fine for me.

C# Threading with HttpRequestMessage headers

I have a number of tasks running concurrently making asynchronous web requests. They all reference a header string which contains an authorisation token required to make a successful request. After some duration the token expires and a new one must be generated for future web requests to work. To do this, each Web Request has a fallback where if it returns an unauthorised error it will send off a new token request and then apply that to the global token string, and then re-run the request.
Imagine I have Tasks A & B performing asynchronous requests. They both receive an unauthorised request error and attempt to generate a new token, however Task A received it before Task B and so has already began the request for a new token.
What would be the best way to ensure the entire operation is thread safe? So that when Task B goes to request a token it realises that Task A is already in the process of doing so, so Task B no longer attempts to send of a token request, but simply waits for Task A to finish and return a value that they both can use.
I thought of simply using a lock, but Task B would only wait to re-generate the token itself and not realise that it can use the recently regenerated value of Task A.
I got around this simply by utilising a lock. I was vastly overthinking my initial approach.

Sign in to OneDrive without typing user informations

I need help to obtain an authorize code, is there any way to get one without accepting anything or any window that pops up. I need this for my service as an automated process.
I tried like a thousand ways but nothing works.
Please does anyone know a solution?
As per the docs (http://msdn.microsoft.com/en-us/library/dn659750.aspx), you can use a refresh token if your app has offline access in its scope.
If offline access is set, when you retrieve your authentication token normally, you'll also get a refresh token. When the normal token expires, you can request a new one similarly to the first token, replacing the code query parameter with the refresh_token parameter.
To be clear, the process looks like this as per the docs:
Send your user to your web service
Direct them to the OneDrive authorise page with the correct parameters (make sure offline access is in the scope)
Wait for them to be redirected back to your app with the authorisation code
Exchange the authorisation code with OneDrive (using the oauth20_token.srf endpoint) to receive a set of tokens (one of these will be refresh)
Wait for the access_token you received to expire
Exchange the refresh_token you received for a new access token as per the "Getting a new access token or refresh token" section of the docs

Categories

Resources