Which OAuth 2.0 / OpenID Connect flow should I choose? - security

I have a scenario where I need to add authentication & authorization to a native iOS / Android application. The app allows employees of a store to perform their business operations:
Every store has an account created for it on the server.
Multiple devices can be used within the same store. All of the devices in the store should access the same data.
Multiple users (employees) can use any of the devices within the store.
Identifying the actual user performing a certain operation is taken care of within the app itself.
I looked at the available flows and I'm a bit confused on what would be the best fit in this scenario.
I thought about using the Device Flow but I am not sure it's the right thing to do here knowing that the mobile device is not an input-constrained device (such as a fitness tracker or a smart TV).
The Client Credentials flow is also not a good fit because a mobile device cannot securely store secrets, and because I'm not just looking for authorizing requests to the server, but also in a way authenticating the store itself so I could return its specific data.
I'm left with the Authorization Code with PKCE flow but I'm still not sure if that's the right way to go knowing that I'm not authenticating users, but rather a device that belongs to a store. So, maybe I can think of the store itself as the Resource Owner and a privileged individual that works in the store (maybe the store owner) would use this flow to authenticate the store.
Do you think (3) is the right approach or do you recommend a different flow?

There are two questions raised by the OP:
Q1. What OAuth 2.0 flow is appropriate for a native mobile app?
Q2. Who is the resource owner and how to go about authenticating them?
A1. Authorization Code with PKCE will work well for the native apps in a store.
A2. Based on the information provided by OP, store itself is a resource owner. Each store has an identity defined in the auth server, presumably with a credential, e.g. a password. In this case this identity will be used by all store employees to authenticate to the auth server. This will simplify token creation because the subject of the token will be the store itself. The identity of the employee will be handled outside of OAuth 2.0 exchange by the application. This will satisfy the requirement that all employees will have access to the same store-wide data. This is easy to implement in the resource server because the subject of the token is the store.
The application will have to be locked to the use of a single identity in a given store. This will avoid human error by an employee who works in multiple stores. This can be done at the application level in several ways.
Store identity can be simply configured by a store admin on each device.
If device rotation is possible between stores or if a personal mobile phone is used by employees and if they travel between stores, then the app could make a call to an API that returns store's identity based on the IP address of the store. This will also restrict use of the app to the internal network.
In either case an employee will only have to enter store password when authenticating to the auth server.

I understand the concerns, since you need a middle ground between security and manageability. Aim for an option that meets immediate requirements but has good future possibilities also.
PREFERRED FLOW
The code flow will be the right choice since it has the best flexibility. Use the AppAuth pattern from RFC8252.
FUTURE PROOF SECURITY
The things to think about for the longer term are the abilities to perform one or both of these, which can be done in various ways:
Identify the user
Identify the device
Code flow allows for various choices:
Convert your current in app user identification to a custom authentication action that runs during the code flow - you might use that as the primary factor, or perhaps as a secondary factor
In future, store employees could sign in via a user friendly device such as a WebAuthn key instead of a password
Mobile apps can store a client credential if it is distinct per device. In higher security setups this can be a strong cryptographic credential. More about this in mobile best practices. This enables you to identify the device.
Of course, you don't need to do all of this, but the tools exist when using the code flow, and adding more advanced security does not usually require any code changes.
INITIAL ROLLOUT
The tricky part is designing an initial rollout without blocking issues. Another option might involve something like 2 user accounts per store - one with admin rights - and use of simple passwords.
You should of course also think through threats - eg how to track the user if a malicious action was performed by one of the employees.

Related

Is it possible to utilise Open ID Connect flows for authentication but then have another source of authorization rules?

My situation is this. I have a legacy Angular application which calls a Node API server. This Node server currently exposes a /login endpoint to which I pass a user/pwd from my Angular SPA. The Node server queries a local Active Directory instance (not ADFS) and if the user authenticates, it uses roles and privileges stored on the application database (not AD) to build a jwt containing this user's claims. The Angular application (there are actually 2) can then use the token contents to suppress menu options/views based on a user's permissions. On calling the API the right to use that endpoint is also evaluated against the passed in token.
We are now looking at moving our source of authentication to an oAuth2.0 provider such that customers can use their own ADFS or other identity provider. They will however need to retain control of authorization rules within my application itself, as administrators do not typically have access to Active Directory to maintain user rights therein.
I can't seem to find an OIDC pattern/workflow that addresses this use case. I was wondering if I could invoke the /authorize endpoint from my clients, but then pass the returned code into my existing Node server to invoke the /token endpoint. If that call was successful within Node then I thought I could keep building my custom JWT as I am now using a mix of information from my oAuth2 token/userinfo and the application database. I'm happy for my existing mechanisms to take care of token refreshes and revoking.
I think I'm making things harder by wanting to know my specific application claims within my client applications so that I can hide menu options. If it were just a case of protecting the API when called I'm guessing I could just do a lookup of permissions by sub every time a protected API was called.
I'm spooked that I can't find any posts of anyone doing anything similar. Am I missing the point of OIDC(to which I am very new!).
Thanks in advance...
Good question, because pretty much all real world authorization is based on domain specific claims, and this is often not explained well. The following notes describe the main behaviors to aim for, regardless of your provider. The Curity articles on scopes and claims provide further background on designing your authorization.
CONFIDENTIAL TOKENS
UIs can read claims from ID tokens, but should not read access tokens. Also, tokens returned to UIs should not contain sensitive data such as names, emails. There are two ways to keep tokens confidential:
The ID token should be a JWT with only a subject claim
The access token should be a JWT with only a subject claim, or should be an opaque token that is introspected
GETTING DOMAIN SPECIFIC CLAIMS IN UIs
How does a UI get the domain specific data it needs? The logical answer here is to send the access token to an API and get back one or both of these types of information:
Identity information from the token
Domain specific data that the API looks up
GETTING DOMAIN SPECIFIC CLAIMS IN APIs
How does an API get the domain specific data it needs from a JWT containing only a UUID subject claim? There are two options here:
The Authorization Server (AS) reaches out to domain specific data at the time of token issuance, to include custom claims in access tokens. The AS then stores the JWT and returns an opaque access token to the UI.
The API looks up domain specific claims when an access token is first received, and forms a Claims Principal consisting of both identity data and domain specific data. See my Node.js API code for an example.
MAPPING IDENTITY DATA TO BUSINESS DATA
At Curity we have a recent article on this topic that may also be useful to you for your migration. This will help you to design tokens and plan end-to-end flows so that the correct claims are made available to your APIs and UIs.
EXTERNAL IDENTITY PROVIDERS
These do not affect the architecture at all. Your UIs always redirect to the AS using OIDC, and the AS manages connections to the IDPs. The tokens issued to your applications are fully determined by the AS, regardless of whether the IDP used SAML etc.
You'll only get authentication from your OAuth provider. You'll have to manage authorization yourself. You won't be able to rely on OIDC in the SAML response or userinfo unless you can hook into the authentication process to inject the values you need. (AWS has a pre-token-gen hook that you can add custom claims to your SAML response.)
If I understand your current process correctly, you'll have to move the data you get from /userinfo to your application's database and provide a way for admins to manage those permissions.
I'm not sure this answer gives you enough information to figure out how to accomplish what you want. If you could let us know what frameworks and infrastructure you use, we might be able to point you to some specific tools that can help.

OAuth for Server to Server API Security

So the past few days I have scoured the internet for API security 'best practises' or techniques, specifically for APIs that are accessed directry FROM a server TO a server (server-to-server). There seems to be many varied opinions, and it's hard to consolidate them into a workable idea.
According to many, OAuth is the way to go. Depending on whether one wishes to not use a secure socket protocol, the choice is either OAuth 1.0A or OAuth 2.0, respectively.
Regarding OAuth, my understanding is that OAuth 1.0A main concern is the digital signage of requests, whereas OAuth 2.0 relies on the underlying HTTPS to guarantee integrity. So am I safe to make the following assumption?
Assumption: If using HTTPS, one does not need to use HMAC or any form of digital signature to prevent replay attacks, man in the middle attacks and to maintain integrity.
This still leaves authorization, which OAuth manages via an exchanged token. But why is it so complex? Can I, for example, give all the servers (private consumers) globally unique usernames and secrets, such that each 'request' is 'signed' with some hash of the secret, username and request parameters?
This, as far as I can tell, implies authorization and authentication. Authentication is managed by the confirmation of the hash, and authorization is prohibited because, critically, every server has the same privileges to their own resources.
As such, what's the best approach when designing an API strictly for server-to-server (or "2-legged") communication? Is it safe to simply use HTTPS, and then sign each request with a personalized hash, implying authentication, authorization and also not requiring the need to maintain state/sessions.
I can understand that conformity to a standard is a benefit to developers writing code to consume the service, and the web culture in general, so adherance to some 'subset' of OAuth sounds appealing; I am just not sure if it's required here.
Assume you have system S1 that already has a trust relationship with system S2. What OAuth does is to provide a mechanism so that S1 can give S3 access to S2. That is, S3 can be given permission to act on S2, using some part of the permissions of S1. It does this in a way that S1 has control of.
Q: "Can I, for example, give all the servers (private consumers) globally unique usernames and secrets"
A: Of course you can do this. If you have username and unique password with every system you want to talk to, then you have no need of OpenID or OAuth. But this becomes very hard to manage. OAuth allows you to have one secret on one system, and authorize any number of other systems based on the one secret. That is the only reason it exists.
If you look at what OAuth does, is that it basically makes a new unique shared secret (called a token, but you can also call it a password if you like) for each kind of access to be given out. That unique secret is generated by S2, but passed from S1 to S3, and can be used as a password by S3 for accessing S2. It is S2 that is "controlling" the access. The only thing that OAuth does is get the token to S3. This eliminates the need to set up a password, and manually carry it between the systems.
When you talk about a "two legged" communications, the question is: how did the shared secret get set up between them? If you manually (i.e. physically carried) and set up both systems with password, then you have no need for OAuth. But that is a lot of trouble if you have a lot of systems. N systems would need (N*(N-1)/2) passwords.
Normally what you want to do, is to have one server act as an "authentication server" and every server has a trust relationship to that. Then, you use OAuth to authorize any interactions between any two other servers. That is what the complexity is all about.
Once you have the basic trust relationship between servers, you can on top of that sign requests or sign responses (for non-repudiation purposes).
When designing a service, you need to think about ways that access might be given out. For example, do you want time-limited access that would be good for only 7 days? Would you want to make "read-only" access available? This will give S1 options on the kinds of access to S2 that it gives to S3.
Let me illustrate with a specific example: Snow is good, and you would like to go skiing. The ski area is open, but all your money is in the bank. What you want to do, is to authorize the ski area to withdraw funds from your bank account. You don't want to give all your money to the ski area. You don't trust them with your complete password. So instead, you first contact the bank, and arrange for a "permission" to withdraw a specific amount of money. This is represented by a token. You then pass that token to the ski area. Using that token, the ski area is able to withdraw the specified amount of funds. The is always responsible for guarding your funds, and it is the bank that defines the kinds of transactions you might be able to set up permissions on. OAuth is just a standard way to pass the token around, securely.
What you've described as solution called "using client certificates for HTTPS communication" or "mutual SSL" - server presents its certificate with domain and client presents certificate somehow identifying itself. Works well for server-to-server cases.
This approach indeed allows to authenticate servers/users in secure and standard way. Your server that receives incoming requests will be able to make authorization decisions based on certificate presented by caller. Calling servers will need to either register they own certificates with your service or obtain your predefined certificates to call your service.
This approach works for cases where you can properly control distribution of client certificates or server accepts certificates obtained in some external way. If you control both ends of communication (i.e. securing traffic between components of your own multi-tiered system) than this approach is one of simplest.

API Keys vs HTTP Authentication vs OAuth in a RESTful API

I'm working on building a RESTful API for one of the applications I maintain. We're currently looking to build various things into it that require more controlled access and security. While researching how to go about securing the API, I found a few different opinions on what form to use. I've seen some resources say HTTP-Auth is the way to go, while others prefer API keys, and even others (including the questions I found here on SO) swear by OAuth.
Then, of course, the ones that prefer, say, API keys, say that OAuth is designed for applications getting access on behalf of a user (as I understand it, such as signing into a non-Facebook site using your Facebook account), and not for a user directly accessing resources on a site they've specifically signed up for (such as the official Twitter client accessing the Twitter servers). However, the recommendations for OAuth seem to be even for the most basic of authentication needs.
My question, then, is - assuming it's all done over HTTPS, what are some of the practical differences between the three? When should one be considered over the others?
It depends on your needs. Do you need:
Identity – who claims to be making an API request?
Authentication – are they really who they say they are?
Authorization – are they allowed to do what they are trying to do?
or all three?
If you just need to identify the caller to keep track of volume or number of API Calls, use a simple API Key. Bear in mind that if the user you have issued the API key shares it with someone else, they will be able to call your API as well.
But, if you need Authorization as well, that is you need to provide access only to certain resources based on the caller of the API, then use oAuth.
Here's a good description: http://www.srimax.com/index.php/do-you-need-api-keys-api-identity-vs-authorization/
API Keys or even Tokens fall into the category of direct Authentication and Authorization mechanisms, as they grant access to exposed resources of the REST APIs. Such direct mechanisms can be used in delegation uses cases.
In order to get access to a resource or a set of resources exposed by REST endpoints, it is needed to check the requestor privileges according to its identity. First step of the workflow is then verifying the identity by authenticating the request; successive step is checking the identity against a set of defined rules to authorizing the level of access (i.e. read, write or read/write). Once the said steps are accomplished, a typical further concern is the allowed rate of request, meaning how many requests per second the requestor is allowed to perform towards the given resource(s).
OAuth (Open Authorization) is a standard protocol for delegated access, often used by major Internet Companies to grant access without providing the password. As clear, OAuth is protocol which fulfils the above mentioned concerns: Authentication and Authorization by providing secure delegated access to server resources on behalf of the resource owner. It is based on access Tokens mechanism which allow to the 3rd party to get access to the resource managed by the server on behalf of the resource owner. For example, ServiceX wants to access John Smith's Google Account on behalf of John, once John has authorized the delegation; ServiceX will be then issued a time-based Token to access the Google Account details, very likely in read access only.
The concept of API Key is very similar to OAuth Token described above. The major difference consists in the absence of delegation: the User directly requests the Key to the service provider for successive programmatic interactions. The case of API Key is time based as well: the Key as the OAuth Token is subject to a time lease, or expiration period.
As additional aspect, the Key as well as the Token may be subject to rate limiting by service contract, i.e. only a given number of requests per second can be served.
To recap, in reality there is no real difference between traditional Authentication and Authorization mechanisms and Key/Token-based versions. The paradigm is slightly different though: instead of keep reusing credentials at each and every interaction between client and server, a support Key/Token is used which makes the overall interaction experience smoother and likely more secure (often, following the JWT standard, Keys and Tokens are digitally signed by the server to avoid crafting).
Direct Authentication and Authorization: Key-based protocols as a variant of the traditional credentials-based versions.
Delegated Authentication and Authorization: like OAuth-based protocols, which in turn uses Tokens, again as a variant of credential-based versions (overall goal is not disclosing the password to any 3rd party).
Both categories use a traditional identity verification workflow for the very first interaction with the server owning the interested resource(s).

How to keep the client credentials confidential, while using OAuth2's Resource Owner Password Credentials grant type

We are building a rest service and we want to use OAauth 2 for authorization. The current draft (v2-16 from May 19th) describes four grant types. They are mechanisms or flows for obtaining authorization (an access token).
Authorization Code
Implicit Grant
Resource Owner Credentials
Client Credentials
It seems we need to support all four of them, since they serve different purposes. The first two (and possibly the last one) can be used from third-party apps that need access to the API. The authorization code is the standard way to authorize a web application that is lucky enough to reside on a secure server, while the implicit grant flow would be the choice for a client application that can’t quite keep its credentials confidential (e.g. mobile/desktop application, JavaScript client, etc.).
We want to use the third mechanism ourselves to provide a better user experience on mobile devices – instead of taking the user to a login dialog in a web browser and so on, the user will simply enter his or her username and password directly in the application and login.
We also want to use the Client Credentials grant type to obtain an access token that can be used to view public data, not associated with any user. In this case this is not so much authorization, but rather something similar to an API key that we use to give access only to applications that have registered with us, giving us an option to revoke access if needed.
So my questions are:
Do you think I have understood the purpose of the different grant types correctly?
How can you keep your client credentials confidential? In both the third and fourth case, we need to have the client id and client secret somewhere on the client, which doesn't sound like a good idea.
Even if you use the implicit grant type and you don’t expose your client secret, what stops another application from impersonating your app using the same authorization mechanism and your client id?
To summarize, we want to be able to use the client credentials and resource owner credentials flow from a client application. Both of these flows require you to store the client secret somehow, but the client is a mobile or JavaScript application, so these could easily be stolen.
I'm facing similar issues, and am also relatively new to OAuth. I've implemented "Resource Owner Password Credentials" in our API for our official mobile app to use -- the web flows just seem like they'd be so horrible to use on a mobile platform, and once the user installs an app and trusts that it's our official app, they should feel comfortable typing username/password directly into the app.
The problem is, as you point out, there is no way for my API server to securely verify the client_id of the app. If I include a client_secret in the app code/package, then it's exposed to anyone who installs the app, so requiring a client_secret wouldn't make the process any more secure. So basically, any other app can impersonate my app by copying the client_id.
Just to direct answers at each of your points:
I keep re-reading different drafts of the spec to see if anything's changed, and am focused mostly on the Resource Owner Password Credentials section, but I think you're correct on these. Client Credentials(4) I think could also be used by an in-house or third-party service that might need access to more than just "public" information, like maybe you have analytics or something that need to get information across all users.
I don't think you can keep anything confidential on the client.
Nothing stops someone else from using your client id. This is my issue too. Once your code leaves the server and is either installed as an app or is running as Javascript in a browser, you can't assume anything is secret.
For our website, we had a similar issue to what you describe with the Client Credentials flow. What I ended up doing is moving the authentication to the server side. The user can authenticate using our web app, but the OAuth token to our API is stored on the server side, and associated with the user's web session. All API requests that the Javascript code makes are actually AJAX calls to the web server. So the browser isn't directly authenticated with the API, but instead has an authenticated web session.
It seems like your use-case for Client Credentials is different, in that you're talking about third-party apps, and are only serving public data through this method. I think your concerns are valid (anyone can steal and use anyone else's API key), but if you only require a free registration to get an API key, I don't see why anyone would really want to steal one.
You could monitor/analyze the usage of each API key to try to detect abuse, at which point you could invalidate one API key and give the legitimate user a new one. This might be the best option, but it's in no way secure.
You could also use a Refresh Token-like scheme for this if you wanted to lock it up a bit tighter, although I don't know how much you would really gain. If you expired the Javascript-exposed api tokens once a day and required the third-party to do some sort of server-side refresh using a (secret) refresh token, then stolen api tokens would never be good for more than a day. Might encourage potential token thieves to just register instead. But sort of a pain for everyone else, so not sure if this is worth it.

Limiting simultaneous authorisations for a user/consumer combination in OAuth 2.0

I'm building a service which will act as an OAuth 2.0 provider. I want to be able to limit the number of simultaneous authorisations that a user has for a specific consumer.
For example, each user of a consumer application should only be able to have, say, three simultaneous authorisations for that consumer, and thus only be able to use three clients simultaneously. When they try and authorise a fourth time it should prompt the user to remove the authorisation for an existing client before they can continue.
In my limited experience of OAuth, the token for a consumer application is always the same for a user and consumer combination, and so there's no way of revoking access to specific clients - only consumers.
Is there any provision in OAuth 2.0 for making a client identifier part of that combination, and thus part of the token? I'm specifically interested in OAuth 2.0 because of the User-Agent flow.
Or am I barking up the wrong tree entirely, and should I be looking at laying different system on top of OAuth?
It seems like you could generate authorization-specific access tokens and include metadata about which client/authorization instance each refers to either on the token itself (encoded form of -1, etc.) or within your app (where each access token is unique). In fact, doing so could probably be considered an improvement over most provider implementations as individual clients could be recognized more easily (for abuse, etc.).
Tokens needn't take on any particular format, so you're free to overload them with as much or as little semantic information as you want and adapt your UI and UX to match.

Resources