I have an application, in which I have to fetch a list of users. The API to fetch the list requires an authentication token, which expires every 1 hour. So, in order to fetch the users, I first need to make a token call and post that I need to make the fetch call. How can I cache the token which is valid for 1 hour in Node? We have multiple pods, so I need a distributed cache to make sure that the token value is the same across the pods. Will it be possible to implement it in node and how to implement it? Any kind of resources/tutorials would be really helpful.
So you're calling an external service, but you need a valid token that you have to obtain first.
Take a look at how existing software tackles it. For example, Microsoft's Graph API SDK (which also uses bearer token auth):
https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CustomAuthenticationProvider.md
You inject an "authentication provider" that authenticates and retrieves a token from the remote service when necessary. Next, when you need to make a call to the API, the client checks if it has a token in-memory. If it doesn't (or if it's expired), it asks the authentication provider for a new token. So, the in-memory cache layer is in the client object.
Another approach is in-memory caching, but in the Authentication Provider layer - then, the client can blindly ask it for a token every time, and let the Provider decide whether to use the current token or ask for a new one.
I would refrain from putting the token on a network-accessible cache - it opens up a potential security hole for leaking the token, and does not seem to serve any purpose.
Related
I am currently writing a social media backend server, which should handle a lot of users.
As authentication mechanism, we want to use Google's & Apple's OIDC Authentication (Sign in with Apple).
Now, as we get a opaque access token, I cant really imagine a performant way to authorize the opaque access token, as we can not decode the token (not jwt token) and we do not know the issuer.
What I thought:
Authorize the access token sequentially one by one. Meaning:
Fetch Google/userinfo from Google
If 401, Fetch Apple/userinfo
This is unperformant, as the processing time is getting bigger, when we add more IDP's
Save the issuer in the DB and fetch the user's issuer always in the authentication step, before fetching the /userinfo endpoint
This is more performant, but it does not feel right, as the webserver has to make a DB call + HTTP call to authorize a request from the client.
Am I missing a method to get this in a performant way?
BTW: The webserver is a node.js application using express.js
Thank you very much in advice!
The key point here is that foreign access tokens are not designed for authorization in your own back end. Instead you need to issue your own tokens when sign in completes.
AUTHORIZATION SERVER (AS)
The most standard solution is for your apps to talk to an AS that you own, and for it to manage the social logins for you. The AS will then issue tokens that you can fully customize.
This will enable you to fully control the scopes and claims your back end uses for authorization, as well as the session times in UIs. Your back end will only ever work with access tokens issued by the AS, regardless of the login method a user selects.
When you need to add a new login method you just change the AS configuration and will not need to change any code in your apps. A good AS will support integrating with many systems, as demonstrated in this summary page.
BACKGROUND
I have an application with a node backend and an angular frontend. The backend has two GraphQl endpoints:
/auth, which has methods like:
signIn, which authenticate an interactive user (basic usr/pwd) from my angular front and and returns an access token and a secure httpOnly refresh token (cookie);
refreshToken, which returns a new access token; and
signOut, which just revokes the refresh token.
/api, which contains the business rules, and authenticates the request by the access token received (stateless)
The angular frontend authenticates the user by calling the /auth/signIn endpoint, keeps the access token in memory, is unaware about the httpOnly refresh token, and creates a timer to call the /auth/refreshToken periodically.
PROBLEM
I need to grant access to my customers to access the /api programmatically too (e.g. from Zapier), so we are talking about an API-KEY, right? I was thinking about creating an API-KEY section in the SETTINGS area in the frontend and CRUDE methods in the /auth endpoint to maintain them. I would create a new special non interactive “user”, in the users table linked to the generated API-KEY so that, for instance, the user Zapier would be related to the API-KEY created to interact with Zapier and I could see its activity along the other users activities at the audit trail and easily revoke it by deleting that user.
QUESTION
Should I use a long term (?) access token as API-KEY? Wouldn't that defeat the purpose of using access tokens? My /api would no longer be stateless and I would have to check the existence of the access token for each request, right? It doesn’t seem the right choice. Is there a better approach?
Using the refresh token as API-KEY doesn’t seem to be an option to me, first, because it doesn't seem to be allowed to set a httpOnly cookie on the client side, second, because the logic to update the access token would be too complex to the user and third, because I wouldn't want to expose the /auth endpoint.
API Keys are very weak security so ultimately this depends on data sensitivity such as whether it is serious if an attacker can access your data easily for a long time.
I would favour a standard OAuth flow for the type of client - perhaps Client Credentials Grant - so that access tokens are used, which are valid for a limited time period, such as 30 minutes. Expiry and refresh coding is well documented online.
If it is a user app then maybe the app (or its back end) needs to do some work to get tokens correctly.
If the customer is writing code to call the API with code then they need to be given guidance on how to authenticate and manage expiry. These details are well documented online.
Attaching a token could even be managed by an outbound proxy if these users are very non technical, where the proxy deals with supplying a token.
I am working on asp.net web api 2 and used JWT for authentication. The application is working fine as it generates token on login request from user, and then user can use that token for subsequent request. But I have some security concerns like
What if the token is stolen from user's browser, How can server detect a valid request among two requests sent from two different computers.
When user will sign out, how server can detect that this particular token is now invalid/loggedout. As I read about log out, it is merely deletion of token from client browser, so stolen token will still be there, requesting from other pc.
How can server revoke a token when expiration period reached?
Please comment if my question is not clear.
Please find the answers as below:
1) Access tokens like cash, if you have it then you can use it, if you have valid access token there is no way to identify if the request is coming Authorized party or not, thats why HTTPS must be used with OAuth 2.0 and bearer tokens.
2) Self contained tokens like JWT are not revocable, so there is no DB checks and this is the beauty of it, you need to leave those tokens until they expire. If you used reference tokens then you will be able to revoke them, but the draw back for this approach is hitting the DB with each API call to validate the token.
3) Already answered in part 2.
You can check my series of posts about this topic using the below links:
Token Based Authentication using ASP.NET Web API 2, Owin, and
Identity.
AngularJS Token Authentication using ASP.NET Web API 2.
JSON Web Token in ASP.NET Web API 2 using Owin.
When it comes to JWT revocation the general idea seems to be either that:
it simply can't be done
or it can be done, but it goes against the stateless nature of JWT.
I generally don't agree with either. First JWT is just a token format (Learn JSON Web Tokens), yes it can be used to shift some state from servers to clients, but that does not impose any restriction on what we can and should do to consider them valid from the point of view of our application.
Second, if you understand the implications and the associated cost of implementing revocation functionality and you think it's worthwhile to use self-contained tokens instead of alternatives that could simplify revocation but increase the complexity elsewhere then you should go for it.
Just one more word on the stateless thing, I think I could only agree to it in the remote chance that the application receiving and validating tokens does not maintain any state at all. In this situation, introducing revocation would mean introducing a persistent store where one did not exist before.
However, most applications already need to maintain some kind of persistent state so adding a few more bits to track blacklisted/invalid tokens is a non-issue. Additionally, you only need to track that information until the token expiration date.
Having covered the general theory, lets go through your individual questions:
If your security requirements mandate that you need to employ additional measures to try to detect malicious use of a token then you're free to do so. A simple example would be blacklisting a token if you detect usage of the same token coming from very different geographical locations.
With support for token revocation in place the application logout scenario would just need to include a step to blacklist the associated token.
I may be missing something here, but if the token expiration time was reached the regular process to validate a JWT would already include a check to make sure that the token was not yet expired.
As I asked described here:
I am building a service where I have code borrowed from the SocialBootstrapApi. I am specfically using the Linkedin oauth2 provider though.
I have no complaints for a single user - the code works nicely, but if the same user logs in simultaneously from two differen machines (using the same linkedin account) the original logins access token is invalidated. While the user stays logged in (because session cookies are already in place) if the user performs an action that uses the expired access token to perform a task that requires a linkedin api call, the call fails with an invalid access token error. Obviously I understand the reason behinds this, but I am not sure how to rectify it. In this mobile first world, we have so many devices and one device can't logoff a user from another device.
So, should I re-get the access token from the UserAuthDetails table everytime before I perform an api call just in case it has been invalidated? Or, shouldn't this be updated in the cache and next time the access token is accessed, the refreshed one is served because the cache has been updated?
Thanks
The easiest option (and my preferred solution) is to just fetch the access tokens from the IAuthRepository before making the API call. IAuthRepository.GetUserAuthDetails() will return the UserAuthDetails that contains the access tokens.
This can be slightly optimized by first attempting to use the access tokens on the session before hitting the UserAuth backend datastore, although as it's likely the cost of the required simple db call to a internal datastore is going to be a lot less than the call to a remote service (i.e. LinkedIn API's) - the optimization may not be worth it. But if you're going with this approach I'd update the Users Session with the fresh access tokens so next time the fresh tokens from the cache can be used.
Each User Session references a different Session in the Cache
Users authenticating from different browsers, pc's, devices, etc are each given their own session which is just the AuthUserSession POCO's stored in the registered ICacheClient referenced by ServiceStack's Session Cookies, i.e. they don't share the same Cache so changes to one of the users session doesn't affect any other Users Sessions.
I figured this has been answered before, but a quick SO search didn't yield anything.
I have a private API that is locked down by an APIKey. This key needs to be passed for each request. With this key you can access any part of the API. Obviously that's pretty open. For the most part this is acceptable. However, there are cases where I want to ensure that the request is sent by the owner of the data.
For example, consider an update or delete request. You shouldn't be able to make this request for someone else's data. So in addition to the APIKey, I'd like to have something else to ensure that this user making the request is authorized to perform that action.
I could require that an ownerID be passed with such request. But that's quickly forged. So what have I gained.
I am interested to hear what other members of SO have implemented in these situations. Individual APIKeys? Dual-authorization?
If it matters, my API follows the REST architecture and is developed with PHP/Apache.
API keys should be unique per user. This will verify the user and that they should have access to the data.
If you want to be even more secure you can have that api secret be used as a refresh token that can be used to retrieve an access token with an automated expiration.
SSL for all requests is also suggested.
Each API user has a unique API key. This key identifies them as a single user of the system. When dealing with more sensitive data, I've used client side certificates for auth, however Basic Auth + requiring SSL is usually sufficient.
When the request comes in, map the API key to the user and then determine if that user "owns" the resource they are trying to interact with.
The whole "determine the owner" part is a separate issue that can be tricky to do nicely in an API depending on how well the system was built. I can share how we've done that in the past as well, but figured that's a bit off topic.
Suggest you should consider using Oauth. In summary this is how it should work.
Each application making the API calls will need the respective application level APIkey for authorization through the Oauth process. Apikey here would just represent the application (client) identity.
Each end-user associated with the usage must authenticate themselves separately (independent of the apikey) during the Oauth authorization process. The users identity, associated context such as scope of authorization is then encoded into a token called access token.
Once the application obtains this access token, all subsequent API calls to access resources should use the access token, until expiry.
On the API implementation side, the access token validation should reveal the end-user context (including the scope of access that is granted during the Oauth process) and hence the access/authorization to use a specific resource can be managed by the resource server.