Emulating M2M auth if the server lacks client_credentials grant type - node.js

Xero Accounting API uses OAuth 2.0 but they seem to have intentionally omitted client_credentials grant type in order to sell what they call Custom Connections.
If we "don't want to pay for a Custom Connection, then you can still make use of Web or PKCE code flow for building machine to machine integrations but you'll need to request your tokens and handle authorisation outside off your application".
So I wonder if there's already a tried and tested way of managing the tokens especially in NodeJS or PHP in GCM or AWS cloud environments that I can use to establish a secure M2M communication after the initial OAuth user login.

Related

OAuth clarification

I've followed a training in Go as an introduction to microservices architecture a while ago. Getting back to this project I realise that I need more context as we've been quickly digging into the details of the implementations at the time...
I've drawn a simplified sequence diagram of 2 simple use cases:
The user logs in
The user is already logged in and make a purchase
(you can comment / modify the diagram at your convenience)
https://drive.google.com/file/d/1gWgkhJipUvWrVidkl7YFt_xlDmZYn_CX/view?usp=sharing
Here are the questions I have:
Here we're dealing with user authentication but what about client authentication? In the case of a web front end client, can I imagine storing an api_key and an api_secret in the env variables for the server that will be hosting this client? Because there use cases where the user is not logged but some services still needs to be available, but at the same time I only want my known clients (the web front and the mobile app) to be able to access those services (putting aside API Gateway solutions, and maybe other API Shields which would probably add another security layer against DOS etc.)
If the client logs in using Google/Facebook, the front app will receive an id_token that needs to be passed to the backend which would then verify the token ( https://developers.google.com/identity/sign-in/web/backend-auth ). In this particular case my OAuth API would not be used. Could please you confirm that it's the way it should be handled?
Many thanks.
EDIT 02/05/2022
Intro / Context
First thing first, Authorization is not Authentication.
Authentication is the process of verifying who a user is,
while authorization is the process of verifying what they have access to.
And like #Max said, OAuth is designed to manage Authorization and Open ID Connect (OIDC) is an extension of OAuth to manage Authentication on top of it.
The diagram I've exposed in my question is known in the OAuth world as the password grant, and, from the official documentation :
Because the client application has to collect the user's password and
send it to the authorization server, it is not recommended that this
grant be used at all anymore.
Authorization of my App (to get access to my APIs)
From the API perspective, we just want to ensure that the incoming requests are coming from the server that is hosting the App. So, in my case, it's simple machine-2-machine communication from backend server to backend server and there's no action required from the user. So, I must implement the Client Credentials Flow
...which would lead me to this flow:
https://drive.google.com/file/d/1qE9JpWRSRPa8z5iNxm7ocGkeT0E149Sv/view?usp=sharing (Feel free to comment / rectify )
Authentication of a user
Because OAuth knows nothing about authentication, I need an OIDC flow. The easiest one is based on the Authorization Code Flow with PKCE from OAuth below (only about authorization) ...
... but the difference is that we're passing an additional scope named openid in the authentication request (step 3), when the app performs the 2nd request to the token endpoint (step 7), the auth server returns an ID Token (which is a JWT containing user info in the payload -> authentication) in addition to the access_token (which do not contain user info but just "random string"). There's other OIDC flows with their pros & cons depending on the situation but it's another topic on its own (https://openid.net/specs/openid-connect-core-1_0.html)
User already identified by Google/Facebook
In case the client logs in using Google, the front app will receive an id_token. This token could be sent to the app server which would then make a request to the API Gateway, which then call the Auth api which would be in charge of verifying the token by calling the 3rd party auth server ( https://developers.google.com/identity/sign-in/web/backend-auth ).
In case of Facebook, we get back an access token, so I don't know how to deal with it ...
https://developers.facebook.com/docs/facebook-login/web
https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow
Using Firebase, there's an onAuthStateChanged callback, so from the App perspective it will prevent request without the user being logged in, but from the API perspective, it doesn't guaranty that a request is coming from a logged in user...
https://firebase.google.com/docs/auth/web/manage-users#get_the_currently_signed-in_user
Warning: the answer below is not complete, it only serves to give a rough idea
Intro
OAuth2 is a protocol for authorization.
Grant Types
Over the OAuth2 protocol, you can use one of the "grant types" or "flow", one of these flows is illustrated in the picture you post and named password grant.
Each of these flows is realized for different scenarios, you rightly point the attention to how securely store the password on a web app.
For example for a front-end authentication (javascript / wasm) you can use a PKCE Flow where the secret_id is not used.
Endpoints
On OAuth2 there are two primary enpoints
Authorize endpoint - where you obtain the authorization code
Token endpoint - where you exchange the authorization code for the token(s)
Tokens
There are two types of tokens on OAuth2
Access Token
Refresh Token
The definition of token on OAuth2 is "an opaque string", you don't need to read it.
The access token is used against the API, this token has an expiration date, when it is expired the system use the refresh token to get another access_token whitout user interaction, when the refresh_token expire the user must re-authenticate again.
You can read the content of the access_token (which is a JWT token) from the JWT.io
Scopes
The Access token has, on its body, the scopes (i.e. Read email, read name, etc).
Scope is a mechanism in OAuth 2.0 to limit an application's access to a user's account.
Identity
On top of the OAuth2 are build other protocols OIDC aka IdToken aka Open Id Connect is one of them, in other terms OIDC protocol use the OAuth2 for establish an Authentication.
With the OIDC there is another token the id_token, this token came with the user's info and is NOT used has Authorizization in front the API.
There are also OIDC flows you can use to get the id_token and/or the access_token.
Conclusion
I suggest you read about OAuth2 from the references below and try different flows using the playground
References
Which oauth2 flow should I use
OAuth2
PKCE in more depth
My advice is to start with the data, which is the deeper area of OAuth.
USE AN AUTHORIZATION SERVER
This will enable you to keep your code simple. It will also handle Google / Facebook and many other forms of authentication for you, with zero impact on your code. The Curity Community Edition is a free and developer friendly option, though there are others. eg Keycloak, Ory Hydra.
PROTECT DATA
OAuth primarily gives you modern ways to protect data. Use scopes and claims to protect data across multiple microservices in a zero trust manner while securely maintaining user context. You will also need to manage joining identity and business data.
IMPLEMENT UI FLOWS CORRECTLY
Mobile apps use the AppAuth pattern. The current best practice for browser based apps is a Backend for Frontend approach. Both of these are tricky.
KEEP CODE STANDARDS BASED
All of the above Curity resources are based on OAuth related standards. If followed your apps will stay simple, with portable code, that can also work with other providers.
OAuth is very architectural though, and the best designs take time to learn, but you can learn the intricacies gradually. Our IAM Primer is a good starting point.

OAuth 2.0 public client impersonation

I'd like to develop a native application (for a mobile phone) that uses OAuth 2.0 Authorization to access protected resources from a resource API. As defined in section 2.1 the type of my client is public.
Upon registration, the Authorization Server provides a client_id for public identification and a redirect_uri.
The client will make use of Authorization Code to receive it's Authorization Grant from the Authorization Server. This all seems secure (if implemented correctly) against any attacker in the middle.
In section 10.2 client impersonation is discussed. In my case, the resource owner grants the client authorization by providing it's credentials via the user agent to the Authorization Server. This section discusses that the Authorization Server:
SHOULD utilize other means to protect resource owners from such
potentially malicious clients. For example, the authorization server
can engage the resource owner to assist in identifying the client and
its origin.
My main concern is that it's easy to impersonate my client once the client_id and redirect_uri is retrieved.
Due to the nature of a public client, this can either be easily reverse engineered. Or in my case, the project will be open source, so this information can be retrieved from the web.
As far as I've understood from section 10.2, it's the resource owner's responsibility to check that the client is legitimate by comparing with what the Authorization Server SHOULD assist with.
In my experience with third party applications requesting an Authorization Grant from me, all I get is a page with some information about the client that actually should be requesting that grant. Based on pure logical sense, I can only judge if the client that's requesting the grant is actually the client that the Authorization Server is telling me who it should be.
So whenever we are dealing with PEBKAC (which I think occurs frequently), isn't it true that impersonators can easily access protected resources if the resource owner just grants them (which might identically look like my legitimate client) authorization?
TLDR - You want oauth access tokens to be issued only to valid clients - in this case devices that installed your app, yes?
First - Oauth2 has multiple workflows for issuing tokens. When YOU are running the Oauth2 service and its issuing tokens to devices running YOUR app, authorization code / redirect URL is not the relevant workflow. I suggest you read my answer here - https://stackoverflow.com/a/17670574/116524 .
Second - No luck here. Just run your services entirely on HTTPS. There is no real way to know whether the client registration request is coming from an app installed from the official app store. You can store bake some secret into the app, but it can be found via reverse engineering. The only possible way this could possibly happen can be some sort of authentication information being provided by the app store itself, which does not exist yet.

API Authorization Strategy

I have a web application in node js that consumes an API for certain aspects of the content of the website e.g news. The API is written in node.js and points to a mongodb database.
I would like some advice as to the best authorization strategy for this type of requirement. I don't really need a user-name and password solution (I don't think). Some sort of static token that the web app can pass to the API so that only applications that have this token can browse the data returned by the API. I mainly want to stop just any old application consuming the API.
Here is best blog that can help you how to authenticate the REST Api in node js with the help of Basic HTTP Authentication, Oauth1 And Oauth2
https://stormpath.com/blog/secure-your-rest-api-right-way
Basically there are the three type of authentication that generally used
Basic Authentication
Oauth1.0a
Oauth2
Http Basic Authentication
More convenient, as you can easily expire or regenerate tokens
without affecting the user's account password.
If compromised, vulnerability limited to API, not the user's master
account
You can have multiple keys per account (e.g. users can have "test"
and "production" keys side by side.)
Oauth1
OAuth 1.0 requires client to send two security tokens for each API call, and use both to generate the signature. It requires the protected resources endpoints have access to the client credentials in order to validate the request.
Oauth2
OAuth 2.0 signatures are not required for the actual API calls once the token has been generated. It has only one security token.
Here describes the difference between OAuth 1.0 and 2.0 and how both.

Application token/secrets when creating an OAuth API

Background: I am using node.js and express to create an API. I have implemented OAuth in my API server in a standard consumer/user key/secret fashion (the same way Twitter, Facebook, etc. do). I expect 3rd parties to connect to my API, again in the same manner as these common APIs.
Normally, a client would connect with an application token/secret (eg, you create a Facebook app as a Facebook developer and these are given to you). However there are times when the client cannot provide a secret for the application because the code is implemented in an insecure fashion. Specifically, I am referring to Javascript libraries. Eg, developers do not want to expose their application secret in Javascript code because it is plaintext and could be read by malicious users.
I've noticed that Facebook avoided this problem. The developer needs to provide only an application token (not secret) to the Javascript library. I do not understand how to provide a similar option for my API without fundamentally making my library insecure. Namely, if requests are being made by a Javascript client library to an API without providing a well-secured token/secret, how are those requests authenticated by the OAuth API?
Intellectually, the best solution I could think of would to have some sort of token handoff between the Javascript client library and the API server via a HTTPS connection, in order to return a secret for the library to use. I'm not quite sure how I'd secure this handoff to prevent spoofs, though.
In most cases it is better to follow the standards than to implement some custom way. OAuth2 specifies 4 methods in the latest draft (28) to do the Authorization Grant flow. The implicit flow is the one you saw on Facebook.
As the standard says for that:
When issuing an access token during the implicit grant flow, the authorization server does not authenticate the client. In some cases, the client identity can be verified via the redirection URI used to deliver the access token to the client. The access token may be exposed to the resource owner or other applications with access to the resource owner's user-agent.
Implicit grants improve the responsiveness and efficiency of some clients (such as a client implemented as an in-browser application) since it reduces the number of round trips required to obtain an access token. However, this convenience should be weighed against the security implications of using implicit grants, especially when the authorization code grant type is available.
it has some security drawbacks.
But as far as I can see, the other methods don't work for you, as they are exposing secrets to either the client (third-party website owner) or the resource owner (user), so you should stay with this.

SSO with CAS or OAuth?

I wonder if I should use the CAS protocol or OAuth + some authentication provider for single sign-on.
Example Scenario:
A User tries to access a protected resource, but is not authenticated.
The application redirects the user to the SSO server.
If beeing authenticated the user gets a token from the SSO server.
The SSO redirects to the original application.
The original application checks the token against the SSO server.
If the token is ok, access will be allowed and the application knows of the user id.
The user performs a log-out and is logged out from all connected application at the same time (single sign-out).
As far as I understand that is exactly what was CAS invented for. CAS clients have to implement the CAS protocol to use the authentication service. Now I'm wondering about to use CAS or OAuth at the client (consumer) site. Is OAuth a replacement for that part of CAS? Should OAuth as a new de-facto standard be preferred? Is there an easy to use (not Sun OpenSSO!) replacement for the authentication part of CAS supporting different methods like username/password, OpenID, TLS certifactes ...?
Context:
Different applications should rely on the authentication of the SSO server and should use something session-like.
The applications can be GUI web applications or (REST) serivces.
The SSO server must be provide a user id, which is necessary to get more information about the user like roles, email and so on from a central user information store.
Single Sign-out should be possible.
Most clients are written in Java or PHP.
I've just discovered WRAP, which could become the OAuth successor. It is a new protocol specified by Microsoft, Google and Yahoo.
Addendum
I've learned that OAuth was not designed for authentication even it could be used to implement SSO, but only together with a SSO service like OpenID.
OpenID seems to me to be the "new CAS". CAS has some features OpenID misses (like single sign-out), but it should not be to hard to add the missing parts in a particular scenario. I think OpenID has broad acceptance and it is better to integrate OpenID into applications or application servers. I know that CAS also supports OpenID, but I think CAS is dispensable with OpenID.
OpenID is not a 'successor' or 'substitute' for CAS, they're different, in intent and in implementation.
CAS centralizes authentication. Use it if you want all your (probably internal) applications to ask users to login to a single server (all applications are configured to point to a single CAS server).
OpenID decentralizes authentication. Use it if you want your application to accept users login to whatever authentication service they want (the user provides the OpenID server address - in fact, the 'username' is the server's URL).
None of the above handle authorization (without extensions and/or customization).
OAuth handles authorization, but it is not a substitute for the traditional 'USER_ROLES table' (user access). It handles authorization for third-parties.
For example, you want your application to integrate with Twitter: a user could allow it to tweet automatically when they update their data or post new content. You want to access some third-party service or resource on behalf of a user, without getting his password (which is obviously unsecure for the user). The application asks Twitter for access, the user authorizes it (through Twitter), and then the app may have access.
So, OAuth is not about Single Sign-On (nor a substitute for the CAS protocol). It is not about you controlling what the user can access. It is about letting the user to control how their resources may be accessed by third-parties. Two very different use-cases.
To the context you described, CAS is probably the right choice.
[updated]
That said, you can implement SSO with OAuth, if you consider the identity of the user as a secured resource. This is what 'Sign up with GitHub' and the likes do, basically. Probably not the original intent of the protocol, but it can be done. If you control the OAuth server, and restrict the apps to only authenticate with it, that's SSO.
No standard way to force logout, though (CAS has this feature).
I tend to think of it this way:
Use CAS if you control/own the user authentication system and need to support a heterogenous set of servers and apps that need centralized authentication.
Use OAuth if you want to support user authentication from systems that you don't own/support (ie Google, Facebook, etc).
OpenID is an authentication protocol, OAuth and OAuth WRAP are authorization protocols. They can be combined with the hybrid OpenID extension.
I'd strongly prefer to see people building on top of standards that have a lot of momentum (more available support, easier to get third parties involved), even if they aren't an exact fit for the application at hand. In this case, OAuth has the momentum, not CAS. You ought to be able to do all or at least nearly all of what you need to do with OAuth. At some later point in the future, OAuth WRAP should simplify things further (it makes some worthwhile trade-offs by using a bearer token and pushing encryption down to the protocol layer), but it's still in its infancy, and in the meantime, OAuth will probably do the job just fine.
Ultimately, if you choose to use OpenID and OAuth, there are more libraries for more languages available to you and to anyone else who needs to integrate with the system. You also have a lot more eyeballs looking at the protocols, making sure they really are as secure as they're supposed to be.
To me, the real difference between SSO and OAuth is grant, not authentication
because a server that implements OAuth obviously has authentication (you have to be logged in to your google, openId or facebook for OAuth to happen with the client app)
In SSO, a power user/sysadmin grants the final user access to an application beforehand on the "SSO app"
In OAuth, final user grants application access to his "data" on the "OAuth app"
I don't see why OAuth protocol couldn't be used as part of an SSO server. Just take out the grant screen from the flow and let the OAuth server lookup the grant from the backing db.
Old post, but this might be useful:
CAS 3.5 will support oAuth as Client and Server.
See: https://wiki.jasig.org/display/CASUM/OAuth

Resources