Should I use an access token as API-KEY? - security

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.

Related

How to handle multiple IDP with opaque access tokens

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.

Should I make 3rd party API calls in backend or frontend?

I have an API and that API needs some data from the Microsft Graph API. I was thinking of implementing an endpoint in my API to refresh the token and use that token to make calls from the frontend. I don't know if that's optimal or safe, hence my question.
EDIT 1: To give a better perspective of what I have, this is the logic I have at the moment. Tell me if this is correct please.
User requests my API's authorization endpoint, which has the Azure's secret key, then the user is redirected to the Microsft oAuth login page. Once logged in oAuth, Microsoft redirects the user to my API, where it saves the JWT tokens in the user's cookies, so the user can refresh the token anytime.
In order to refresh the token, the user simply just makes a call to myapi.com/auth/microsoft/token, where it has the secret key, and it refreshes.
Generally I would recommend always making the 3rd party calls from the back end. It gives you more control and avoids any cross origin complications.
You also want to be aware of any API keys. Most APIs require a key for access and often that key is private and you wouldn't want to share on the front end.
MS Azure APIs have an application and secret token. You cannot expose the secret token to the client. To call directly from the client you would use OAuth to get a JWT token and then you can call from the SPA into the MS Web APIs with that token.
https://learn.microsoft.com/en-us/azure/active-directory/develop/authentication-scenarios#single-page-application-spa
In contrast, there are other 3rd party APIs that are designed to be called only from the front-end. Stripe for example is a payment processing API where the UI can call directly into Stripe and then the client's payment information is never actually passed to the host application, only to Stripe. This improves security.

JWT Token strategy for frontend and backend

I'm writing an application with a front end in emberjs and backend/server-side in a nodejs server. I have emberjs configured so that a user can login/signup with an 3rd party Oauth (google, twitter, Facebook). I have a backend written in express nodejs server that hosts the RESTful APIs.
I do not have DB connected to emberjs and I don't think I should anyways since it's strictly client side code. I'm planning on using JWT for communicating between client side and server side. When a user logins with their oauth cred, I get a JSON object back from the provider with uid, name, login, access_token and other details.
I'm struggling with picking a strategy on how to handle user signup. There is no signup process since it's OAuth. So the flow is if the user is not in my db, create it. I do not support email/password authentication. What would be the flow when a user signs in with an OAuth provider for the first time? Should emberjs send all the details to the backend on every sign in so that backend can add new users to the db?
What should be part of my JWT body? I was thinking uid and provider supplied access token. One issue I can think of here is that provider specific access token can change. User can revoke the token from provider's site and signs up again with emberjs.
I'm open to writing the front-end in any other javascript client side framework if it makes it easier.
If we're talking about not only working but also secure stateless authentication you will need to consider proper strategy with both access and refresh tokens.
Access token is a token which provides an access to a protected resource.
Expiration here might be installed approximately in ~1 hour (depends on your considerations).
Refresh token is a special token which should be used to generate additional access token in case it was expired or user session has been updated. Obviously you need to make it long lived (in comparison with access token) and secure as much as possible.
Expiration here might be installed approximately in ~10 days or even more (also depends on your considerations).
FYI: Since refresh tokens are long lived, to make them really secure you might want to store them in your database (refresh token requests are performed rarely). In this way, let's say, even if your refresh token was hacked somehow and someone regenerated access/refresh tokens, of course you will loose permissions, but then you still can login to the system, since you know login/pass (in case you will use them later) or just by signing in via any social network.
Where to store these tokens?
There are basically 2 common places:
HTML5 Web Storage (localStorage/sessionStorage)
Good to go, but in the same time risky enough. Storage is accessible via javascript code on the same domain. That means in case you've got XSS, your tokens might be hacked. So by choosing this method you must take care and encode/escape all untrusted data. And even if you did it, I'm pretty sure you use some bunch of 3rd-party client-side modules and there is no guarantee any of them has some malicious code.
Also Web Storage does not enforce any secure standards during transfer. So you need to be sure JWT is sent over HTTPS and never HTTP.
Cookies
With specific HttpOnly option cookies are not accessible via javascript and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS.
However, cookies are vulnerable to a different type of attack: cross-site request forgery (CSRF).
In this case CSRF could be prevented by using some kind of synchronized token patterns. There is good implementation in AngularJS, in Security Considerations section.
An article you might want to follow.
To illustrate how it works in general:
Few words about JWT itself:
To make it clear there is really cool JWT Debugger from Auth0 guys.
There are 2 (sometimes 3) common claims types: public, private (and reserved).
An example of JWT body (payload, can be whatever you want):
{
name: "Dave Doe",
isAdmin: true,
providerToken: '...' // should be verified then separately
}
More information about JWT structure you will find here.
To answer the two specific questions that you posed:
What would be the flow when a user signs in with an OAuth provider for
the first time? Should emberjs send all the details to the backend on
every sign in so that backend can add new users to the db?
Whenever a user either signs up or logs in via oauth and your client receives a new access token back, I would upsert (update or insert) it into your users table (or collection) along with any new or updated information that you retrieved about the user from the oauth provider API. I suggest storing it directly on each users record to ensure the access token and associated profile information changes atomically. In general, I'd usually compose this into some sort of middleware that automatically performs these steps when a new token is present.
What should be part of my JWT body? I was thinking uid and provider
supplied access token. One issue I can think of here is that provider
specific access token can change. User can revoke the token from
provider's site and signs up again with emberjs.
The JWT body generally consists of the users claims. I personally see little benefit to storing the provider access token in the body of a JWT token since it would have few benefits to your client app (unless you are doing a lot of direct API calls from your client to their API, I prefer to do those calls server-side and send my app client back a normalized set of claims that adhere to my own interface). By writing your own claims interface, you will not have to work around the various differences present from multiple providers from your client app. An example of this would be coalescing Twitter and Facebook specific fields that are named differently in their APIs to common fields that you store on your user profile table, then embedding your local profile fields as claims in your JWT body to be interpreted by your client app. There is an added benefit to this that you will not be persisting any data that could leak in the future in an unencrypted JWT token.
Whether or not you are storing the oauth provider supplied access token within the JWT token body, you will need to grant a new JWT token every time the profile data changes (you can put in a mechanism to bypass issuing new JWT tokens if no profile updates occurred and the previous token is still good).
In addition to whatever profile fields you store as claims in the JWT token body, I would always define the standard JWT token body fields of:
{
iss: "https://YOUR_NAMESPACE",
sub: "{connection}|{user_id}",
aud: "YOUR_CLIENT_ID",
exp: 1372674336,
iat: 1372638336
}
For any OAuth workflow you should definitely use the passportjs library. You should also read the full documentation. It is easy to understand but I made the mistake of not reading the the whole thing the first time and struggled. It contains OAuth Authentication with over 300 Providers and Issuing Tokens.
Nevertheless, if you want to do it manually or want a basic understanding, here is the flow that I'd use:
Frontend has a login page listing Sign-in with Google/Facebook etc where OAuth is implemented.
Successful OAuth results in a uid, login, access_token etc. (JSON object)
You POST the JSON object to your /login/ route in your Node.js application. (Yes, you send the whole response regardless if it's a new or existing user. Sending extra data here is better than doing two requests)
The backend application reads the uid and the access_token. Ensure that the access_token is valid by following (https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken) or asking for user data from the provider using the access token. (This will fail for invalid access token since OAuth access tokens are generated on a per app/developer basis) Now, search your backend DB.
If the uid exists in the database, you update the user's access_token and expiresIn in the DB. (The access_token allows you to get more information from Facebook for that particular user and it provides access for a few hours usually.)
Else, you create a new user with uid, login etc info.
After updating the access_token or creating a new user, you send JWT token containing the uid. (Encode the jwt with a secret, this would ensure that it was sent by you and have not been tampered with. Checkout https://github.com/auth0/express-jwt)
On the frontend after the user has received the jwt from /login, save it to sessionStorage by sessionStorage.setItem('jwt', token);
On the frontend, also add the following:
if ($window.sessionStorage.token) {
xhr.setRequestHeader("Authorization", $window.sessionStorage.token);
}
This would ensure that if there is a jwt token, it is sent with every request.
On your Node.js app.js file, add
app.use(jwt({ secret: 'shhhhhhared-secret'}).unless({path: ['/login']}));
This would validate that jwt for anything in your path, ensuring that the user is logged-in, otherwise not allow access and redirect to the login page. The exception case here is /login since that's where you give both your new or unauthenticated users a JWT.
You can find more information on the Github URL on how to get the token and to find out which user's request you are currently serving.

Secure data access to RESTful API

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.

What is token-based authentication?

I want to understand what token-based authentication means. I searched the internet but couldn't find anything understandable.
I think it's well explained here -- quoting just the key sentences of the long article:
The general concept behind a
token-based authentication system is
simple. Allow users to enter their
username and password in order to
obtain a token which allows them to
fetch a specific resource - without
using their username and password.
Once their token has been obtained,
the user can offer the token - which
offers access to a specific resource
for a time period - to the remote
site.
In other words: add one level of indirection for authentication -- instead of having to authenticate with username and password for each protected resource, the user authenticates that way once (within a session of limited duration), obtains a time-limited token in return, and uses that token for further authentication during the session.
Advantages are many -- e.g., the user could pass the token, once they've obtained it, on to some other automated system which they're willing to trust for a limited time and a limited set of resources, but would not be willing to trust with their username and password (i.e., with every resource they're allowed to access, forevermore or at least until they change their password).
If anything is still unclear, please edit your question to clarify WHAT isn't 100% clear to you, and I'm sure we can help you further.
From Auth0.com
Token-Based Authentication, relies on a signed token that is sent to
the server on each request.
What are the benefits of using a token-based approach?
Cross-domain / CORS: cookies + CORS don't play well across different domains. A token-based approach allows you to make AJAX
calls to any server, on any domain because you use an HTTP header
to transmit the user information.
Stateless (a.k.a. Server side scalability): there is no need to keep a session store, the token is a self-contained entity that conveys all the user information. The rest of the state lives in cookies or local storage on the client side.
CDN: you can serve all the assets of your app from a CDN (e.g. javascript, HTML, images, etc.), and your server side is just the API.
Decoupling: you are not tied to any particular authentication scheme. The token might be generated anywhere, hence your API can
be called from anywhere with a single way of authenticating those
calls.
Mobile ready: when you start working on a native platform (iOS, Android, Windows 8, etc.) cookies are not ideal when consuming a
token-based approach simplifies this a lot.
CSRF: since you are not relying on cookies, you don't need to protect against cross site requests (e.g. it would not be possible to
sib your site, generate a POST request and re-use the existing authentication cookie because there will be none).
Performance: we are not presenting any hard perf benchmarks here, but a network roundtrip (e.g. finding a session on database)
is likely to take more time than calculating an HMACSHA256 to
validate a token and parsing its contents.
A token is a piece of data which only Server X could possibly have created, and which contains enough data to identify a particular user.
You might present your login information and ask Server X for a token; and then you might present your token and ask Server X to perform some user-specific action.
Tokens are created using various combinations of various techniques from the field of cryptography as well as with input from the wider field of security research. If you decide to go and create your own token system, you had best be really smart.
A token is a piece of data created by server, and contains information to identify a particular user and token validity. The token will contain the user's information, as well as a special token code that user can pass to the server with every method that supports authentication, instead of passing a username and password directly.
Token-based authentication is a security technique that authenticates the users who attempt to log in to a server, a network, or some other secure system, using a security token provided by the server.
An authentication is successful if a user can prove to a server that he or she is a valid user by passing a security token. The service validates the security token and processes the user request.
After the token is validated by the service, it is used to establish security context for the client, so the service can make authorization decisions or audit activity for successive user requests.
Source (Web Archive)
Token Based (Security / Authentication)
This means that in order for us to prove that we’ve access we first have to receive the token. In a real-life scenario, the token could be an access card to the building, it could be the key to the lock to your house. In order for you to retrieve a key card for your office or the key to your home, you first need to prove who you are and that you in fact do have access to that token. It could be something as simple as showing someone your ID or giving them a secret password. So imagine I need to get access to my office. I go down to the security office, I show them my ID, and they give me this token, which lets me into the building. Now I have unrestricted access to do whatever I want inside the building, as long as I have my token with me.
What’s the benefit of token-based security?
If we think back on the insecure API, what we had to do in that case was that we had to provide our password for everything that we wanted to do.
Imagine that every time we enter a door in our office, we have to give everyone sitting next to the door our password. Now that would be pretty bad because that means that anyone inside our office could take our password and impersonate us, and that’s pretty bad. Instead, what we do is that we retrieve the token, of course together with the password, but we retrieve that from one person. And then we can use this token wherever we want inside the building. Of course, if we lose the token, we have the same problem as if someone else knew our password, but that leads us to things like how do we make sure that if we lose the token, we can revoke the access, and maybe the token shouldn’t live for longer than 24 hours, so the next day that we come to the office, we need to show our ID again. But still, there’s just one person that we show the ID to, and that’s the security guard sitting where we retrieve the tokens.
The question is old and the technology has advanced, here is the current state:
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for passing claims between parties in web application environment. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context.
https://en.wikipedia.org/wiki/JSON_Web_Token
It's just hash which is associated with user in database or some other way. That token can be used to authenticate and then authorize a user access related contents of the application. To retrieve this token on client side login is required. After first time login you need to save retrieved token not any other data like session, session id because here everything is token to access other resources of application.
Token is used to assure the authenticity of the user.
UPDATES:
In current time, We have more advanced token based technology called JWT (Json Web Token). This technology helps to use same token in multiple systems and we call it single sign-on.
Basically JSON Based Token contains information about user details and token expiry details. So that information can be used to further authenticate or reject the request if token is invalid or expired based on details.
When you register for a new website, often you are sent an email to activate your account. That email typically contains a link to click on. Part of that link, contains a token, the server knows about this token and can associate it with your account. The token would usually have an expiry date associated with it, so you may only have an hour to click on the link and activate your account. None of this would be possible with cookies or session variables, since its unknown what device or browser the customer is using to check emails.

Resources