IdentityServer4 how to store and renew tokens in authorization code flow - access-token

I am looking for the best approach to work with the IdentityServer4 autorization code flow.
My apps system is quite ordinary: I have an MVC client, a WebAPI and the IS. I also use AJAX to request the API from the client side. So I need the access token on the client side to put it into the authorization header.
Is it good idea to store access token in the cookies?
Do I need self-contained or reference token (it is about security, I suppose)?
What is the best approach to renew when it was expired?
I thought about the two strategies:
Update access token when the first 401 status code was recieved. Can be the problem cause I send more than 1 query to the API and I need to synchronized them and recall the first one (to get result);
Every time before API calling call the MVC client method with GetTokenAsync, check the expire time and get or update and get access token. Seems cheating, cause I need to call the MVC client every time when I want to call the API.
Could you help me to find the best way?

"Is it good idea to store access token in the cookies?"
No, not with the authorization code flow. If you are using an MVC web application you should find a way to store tokens in some kind of datastore away from the browser. All the MVC application should administer is a cookie to access future MVC endpoints (that will make subsequent calls to Identity Server with the appropriate access token in the datastore).
"Do I need self-contained or reference token (it is about security, I suppose)?"
That's all up to you and what you think is best for your use cases. If you'd like to see the information in the access token and skip the extra backend call for validation then use reference tokens. Strategy 2 requires you to use self-contained tokens so that you can check the expiry.
"Could you help me to find the best way?
I don't know if I can give the "best" way, but I'd probably go with strategy 2 and use self-contained tokens.
EDIT: If you wanted to use "axios , to get data from the API" then I would suggest using the implicit flow which has no concept of a refresh token. In this case, leaving it in the cookie should be OK.

Related

How to access a secured API in the frontend?

There is a lot of good content on the internet that explains how to secure a Spring API with Keycloak: Create a Client that represents the API Service in Keycloak and use a link like the one below to get the access and refresh token:
<Domain>/auth/realms/<realm>/protocol/openid-connect/auth/{some parameters}
This yields both tokens. So far so good.
Now, however, I am not sure how the flow for the frontend accessing the API should look like.
Should the frontend directly access this endpoint and, therefore, obtain the access and refresh token? That would mean that the API can only have the access-type public because there is no way to store the client (the API) secret securely.
Or should there be a third server that somehow stores the refresh token for each user, that the user can call if his access token is no longer valid. This server would then use the client's refresh token (and the client secret that could be stored securely, since it would be in the backend) to get a new access token from Keycloak and would forward it to the user.
I guess the main question that I am asking is, whether the client/user should get the refresh token.
If one needs to implement a logic according to the second option, I would be interested in a link or description of how something like this can be done in Spring.
I think, in either case you need to use the Authorization Code Flow. The implicit flow, which was recommended for SPAs (frontends without a backend server) in former versions of OAuth2 must not be used anymore.
The best option is to have a backend server, so the user retrieves the auth code via redirection and the backend server exchanges this auth code with the access and refresh tokens (and keep them without forwarding them to the frontend).
If there is no backend in place and your frontend needs to retrieve and hold the tokens directly, I would recommend to use the Authorization Code Flow with a public client and the PKCE extension (which - put simply - ensures that the entity asking for the auth code is the same as the entity asking for the tokens and that the auth code was not stolen and used by a foreign entity). There are several sources with more detailed explanations, which might help you, for example: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce
Hope this helps you with your architectural considerations.

How to make Web Api secure against CSRF attacks in ASP.NET?

Consider a web application that consists of only HTML and JS for Front end and that communicates with a Web API.
I am trying to protect my application against CSRF attacks and for that I have took reference of this article.
Using the methods in this article, I am able to generate Anti CSRF tokens and pass it to the client. However it depends on first AJAX call that must happen before making regular CRUD operation calls.
With this approach, I need some clarity on few things as well as some alternatives if any. Consider a client visits this web application (which is protected by AJAX based Anti CSRF token), and keeping his session open, he visits a malicious website that contains page that makes the same AJAX calls to get CSRF tokens (assume that attacker is aware of this process), I suppose he can use the headers to make unintended calls thus resulting in an attack.
So how can I protect my application against these?
Please provide more detail regarding this, or if its misleading then help me by providing correct details so that I can tackle it better.
First of all you should use an encrypted communication with the server so the attacker won't be able to read any header data.
If your attacker uses the same calls as you do, he is not be able to guess the anti XSRF token that you use in your calls. A new token is generated for every call to your API. I hope this page helps you with some details:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
I think if we use token based authentication, client have to pass authentication token in each request. And if client do not store it in browser cache and store it in localStorage then browser will not send token in call automatically. And if our service receive any request without auth token then it will discard the request.

Does custom security HTTP headers violate separation of concerns

Does custom application specific, security related HTTP headers violate separation of concerns, is it considered a bad practice? I realize using custom header to control the service would tightly couple the client with the service implementation. Or in this case, to control the security framework behavior. The context where I planned using the custom header is the following:
We are using token based authentication, where token has a fixed lifetime, and new token is issued each time authenticated client calls the web API. SPA client may call the server with AJAX in two contexts
User action (navigation and submit)
Automatic refresh (current view re-fetches data at fixed intervals)
Now, if user leaves the page open, the session never expires, as new token is generated for each automatic fetch. Somehow, we need to differentiate user action from automatic refresh in the server side, and issue new token only for user actions.
I realize Websocket based refresh would be one solution, but we have decided to stick with timed AJAX call due specific matters. Another solution would be to provide token refresh as a separate endpoint, but this would violate the DRY principle from client's perspective, and would be more cumbersome to setup with Spring Security.
Only remaining option is to embed the user/automated information in the request itself, and using a header seems a viable option here. A presence of certain header would prevent the token refresh. Easy to implement with a few lines of code.
I'm only concerned, if this couples the client too much with the service implementation. Technically, it doesn't couple client with the service, but the preceding security filter, thus leaking security concerns in the user interface. Ideally security stuff should be transparent to user interface, so new client could be coded without knowing anything about security (especially when cookies are used).
In the other hand, this solution isn't destructive or mutative. It's an optional feature. By client utilizing it, security is enhanced, but in either case never reduced (from the perspective of server, as it is). Now the question is, what principles using a optional header to enhance security is violating, and is it a valid solution in this context?
In my option the security should be maximized transparently, but I don't see how to not leak security concerns in the client in this situation.
It sounds like you're using your own home-built custom Token Authentication solution here. This is not a good idea.
I'll take a moment to explain WHY you don't want to do what you're proposing, and then what the better option is.
First off -- the problem that you're trying to solve here is that you don't want a user to remain logged into your site forever if they leave a tab open. The reason you need to fix this is because right now, you're assigning a new Access Token on EVERY REQUEST from the user.
The correct solution to handling the above problem is to have two types of token.
An Access Token that has a very short lifetime (let's say: 1 hour), and a Refresh Token that has a longer lifetime (let's say: 24 hours).
The way this should work is that:
When the user first authenticates to your service, the Access and Refresh tokens are generated with their respective timeouts.
These tokens are both set in HTTP cookies that the client-side JS cannot access.
From this point on, every time your user's browser makes a request to your service, you'll parse out the Access token from the cookie, check to see if it's valid, then allow the request.
If the Access token is no longer valid (if it has expired), you'll then parse out the Refresh token from the cookie, and see if that is valid.
If the Refresh token is valid, you'll generate a NEW Access token with another 1 hour lifetime, and override the old Access token cookie with the new on.
If the Refresh token is invalid, you'll simply return a 301 redirect to the login page of your app, forcing the user to manually re-authenticate again.
This flow has a number of benefits:
There is a maximum session length, which is technical (duration of Refresh token + duration of Access token) -- aka: 25 hours in this example.
Access tokens are short lived, which means that if a token is somehow compromised, attackers can't use it for very long to impersonate the user.
What's nice about the above flow is that it is a web authorization standard: OAuth2.
The OAuth2 Password Grant flow does EXACTLY what you're describing. It generates both types of tokens, handles 'refreshing' tokens, handles the entire thing from start to finish in a safe, standards-compliant way.
What I'd highly recommend you do is implement an OAuth2 library on both your server and client, which will take care of these needs for you.
Now -- regarding the tokens, most OAuth2 implementations now-a-days will generate tokens as JSON Web Tokens. These are cryptographically signed tokens that provide a number of security benefits.
Anyhow: I hope this was helpful! I author several popular authentication libraries in Python, Node, and Go -- so this comes from my direct experience working with these protocols over the last several years.

Authorize PHP application permanently to make requests to JWT auth protected API

Maybe I searched with the wrong keywords but I never found anything about the following scenario:
I have both an API with JWT auth (Laravel + tymon/jwt-auth) and a PHP application that should query that API protected by a JWT token.
How can I make sure that the app always is authentificated? After reading a lot of tutorials and article about JWT auth I'm left with this ideas:
using a never expiring token which is stored permanently in the consuming application. If I understand it right this could be a security concern because someone who has access to that token has access to the api as long as he want? But I don't understand why this token shouldn't be invalidated if the token has been stolen?
refresh the token on every request and invalidate the old one. This implies that the consuming application have to update the token after each request in it's storage (database would make the most sense, I guess). In my opinion this produces a lot of overhead and it doesn't prevent for jwt-auth's refresh_ttl setting.
using an additional API request (perhabs cron based?) to a refresh route to prevent the token from expiring. Again there is the jwt-auth's refresh_ttl problem I think.
I wonder why there seems to be no discussions/articles about that scenario.
Any help on that subject I would very much welcome!
You don't want your user logging in every time but you also don't want them to be logged forever.
Here are my thoughts
I have worked with 1 year tokens for comercial applications, I was using it for low level third party developers, the api concept was already overwhelming for them so I went easy on the auth thingy. Once every year their application broke and they had to reach out to get the new token, bad design but it worked.
Refreshing your token on every request will kill your performance and let attackers have a consistent way to break/predict your key, no good.
In my opinion, this is your most elegant suggestion. You could use some PWA features to accomplish that.
I would suggest increasing the refresh_ttl to 30 days and keep the ttl on one hour.
If you're using SPA or heavy js apps:
On your javascript you could do an ajax setup (or prototype or whatever your javascript framework uses for oop) and have a call to refresh whenever you get a .
If you're using just common page refresh for your apps, store you JWT on a cookie, then your application can refresh it whenever it needs and there will be no special js to make. HTTPS will take care of security.

AJAX calls within MVC and Identity Server

I have been playing with Thinktecture IdentityServer3 and am keen to use it as the product looks great. However, I don't fully understand how to accomplish my flow which is probably fairly common:
Create Identity Server using Implicit flow
Setup an MVC web site
Setup a separate Web API
So far so good, as demonstrated in the examples on the site. I now wish to call the API using AJAX calls directly but for this i need an access token. It seems like a large overhead to have to route these through the MVC site itself (again, in the examples).
How can I accomplish this flow? Would it essentially blend the MVC and Javascript Client samples or is there a smoother way so the user only has to sign in once? Perhaps send the access token in a hidden field but then how would it renew?
Any help on understanding this would be great.
I've managed to come up with a solution which seems to work, not sure if it's best practice though...
Expose a method on the MVC site at AJAX/AccessToken
Method should be locked down with Authorize attribute to ensure the MVC part of the site is authenticating properly with IdentityServer
Method returns the users Access Token which was generated through the above call via MVC controllers
In JavaScript, simply use this endpoint to get an Access Token and then call the API manually
The call to get the Access Token should be secure as its within the same domain/authentication model as the MVC site itself
I've put up a sample here for anyone interested:
OIDC-Website
Check out the form post client to see the endpoints being called explicitly. You will need to hit the token endpoint to get your access token.
You should be able to use these endpoints in your AJAX calls, store the received claims and tokens in a cookie and take it from there.
Note that to renew the access token, you will also need to store the refresh token. The Implicit flow does not allow for refresh tokens (you'll need to use the Authorization Code Flow or the Hybrid Flow).

Resources