Is OAuth 2.0 redundant/unnecessary if the client is the same as the resource owner? - api

In section 1.1 of RFC 6749, there are four roles: resource owner, resource server, client, and authorization server.
Does OAuth become redundant or unnecessary if the client and the resource owner are the same entity?
For example, I have a closed API and a front-facing web server. (The front-facing web server would be both the client and the resource owner.) I am trying to decide whether to switch to OAuth 2 authentication instead of using the current username/password authentication method. Is there any added security for moving to OAuth 2 if the API remains closed to third-party applications? (That is, no third-parties will ever have access to the API.)
Thanks!

In the case where the Resource Owner and Client/Resource Server roles coincide OAuth 2.0 may become less relevant from a security point of view, since one of the primary objectives of OAuth not to expose primary credentials of the user to the client becomes moot. That is also the reason why the so-called Resource Owner Password Credentials grant is considered to be a legacy/deprecated flow.
However, it may still make sense to follow the OAuth 2.0 pattern for a number of reasons:
the ability to leverage a standardized protocol through stock libraries and
frameworks without relying on custom code
the fact that in your case the Resource Server is still made strictly OAuth 2.0 compliant, dealing with Clients presenting access tokens, irrespective of what the Client/Resource Owner relationship/implementation is; this would make it easier to allow for 3rd-party client access in a future scenario
the fact that you concentrate verification of user credentials on a single path between Client and Authorization Server so each of your Resource Servers don't need to be bothered by checking user credentials individually, possibly dealing with different authentication mechanisms
and perhaps most importantly, also security-wise: once the user has authenticated through the Client using his primary credentials, the Authorization Server can issue a refresh token as well as an access token; the Client can store and use the refresh token to a new access token when the old one expires; this frees the Client from storing the primary user credentials if it wants to keep accessing the API for a long period of time without requiring explicit user interaction and authentication and makes the resulting system less vulnerable for leakage/loss of user credentials since the user credentials (password) are not stored in the Clients

If you have the following issue then you should use OAuth;
Let's say you a Gmail like web mail provider. Some of your users are using a third party app which logs in into your user's account and auto replies certain emails for you. Or you are Facebook like social network web site where some of your users use a third party app which analyzes your friend networks and prints a 2D graph for you. In this case your users are giving away their usernames and passwords. How would they prevent a certain third party app accessing their account after they gave away their username and password? Simply by changing their password. Now you have another problem; other third party apps won't be able to access the user's account. Then the user have to re-give away his password to other apps he trusts. Now this is problem too because it is not user friendly. OAuth is simply a temporary password that your user gives away to a third party app developer. He can revoke it whenever he wants without changing his own password.
Other than that OAuth is unnecessary. Just use a session cookie if you are not going to have third party app developers. It is a random string stored in user side. And on the server side will have whatever you want. Just look how PHP sessions are used and stored on server side. You can define their lifespan and refresh time automatically from php.ini.

Related

Securely using JSON web tokens to programmatically authenticate a user from one system into another

My team and I have been working on a web application for our clients that uses JSON web tokens for authentication and authorization. Using Azure AD as our identity provider, we verify a user's identity and generate a signed JWT with the user's permissions in it. The JWT then gets included in the authorization header of all subsequent requests to the APIs. Pretty standard stuff as far as JWTs go.
We're now being asked to provide the capability to link directly into our system from another third-party web application without forcing the user to reauthenticate. I'm trying to figure out if there's a way to do so without creating a massive security loophole.
The way I picture this working would be to implement an endpoint for programmatic authentication in our system that accepts a cryptographically signed payload with an API key and the user's ID or email address. The third-party system would have a private key with which to sign the payload, and we'd have a public one to verify the signature. If the request is legitimate, we'd issue a token for the specified user, and they could use that to link to whatever they like.
I'm already getting yelled at by at least one person that this is a complete joke from a security standpoint because, among other things, it completely bypasses AAD authentication. I believe the third-party system in question does use AAD for authentication, but that's not really relevant either way because we're trusting them implicitly whether they've authenticated their users or not. Either way I take his point.
I'm not a security expert and I don't claim to know whether there even is a proper way to do this kind of thing, but from my vantage it doesn't really seem all that much less secure than any other mechanism of authentication and authorization using JWTs. Is that true? Are we nuts for even trying? Is there a way to do it that's more secure? What should I know about this that I demonstrably don't already?
Thanks in advance for the help. At the very least I hope this spurs some helpful conversation.
Single Sign-On (SSO) enables users to enter their credentials once to sign in and establish a session which can be reused across multiple applications without requiring to authenticate again. This provides a seamless experience to the user and reduces the repeated prompts for credentials.
Azure AD provides SSO capabilities to applications by setting a session cookie when the user authenticates the first time. The MSAL.js library allows applications to leverage this in a few ways.
MSAL relies on the session cookie to provide SSO for the user between different applications.
Read more in this documentation.

Developing a RESTful API with OAuth and/or OpenID

Im struggling to wrap my head around implementing OAuth or OpenID with multiple external token providers. Since from my perspective the providers like google mix both specs in a single api, im differentiating these two mechanism in the way i protect my ressources and deal with user data. OpenID is only used for authentication and i produce my own access_tokens and persist all of the user data myself, while on the other hand OAuth provides external access_tokens and manages user data.
Entities involved:
External provider - which is my term for the OAuth/OpenID provider like Google OAuth
Backend - Server which serves primarily as a RESTful API for the clients
Clients - Apps (e.g SPA, IOS App, Desktop clients) which need to access ressources provided by the backend
Im developing an express backend (rest api) for several different sort of clients including web, ios/android. From my understanding i have the following options: (referring to most implementation docs of the provider i want to use instead of the spec)
Option 1 - OpenID
The client acquires an auth_code by signing in with any external provider (Apple, Google, Facebook)
The client sends this auth_code to my backend where this code is used to issue an id_token
The backend uses this id_token to authenticate the user and store any required information about the user
The backend generates an access/refresh token for authorization and sends these back to the client
Now i can use my access_token for authorization and the refresh token for auth-state-management (signout, invalidate tokens)
Problem - Is there a problem really ?
Im not sure if i need to frequently check if the user is still a valid identity. With valid identity i mean wether the external identity (e.g. google user) still exists, which basically relates to wether my persistance layer has to invalidate (delete) this user. In other words do i have to sync my persistance layer with the external provider to avoid dead/unusable identities. This is especially a problem if information like the email address changes and my backend does not get notified about that. Or should i just live with the fact that the user in my backend is just related to the external user by the id and the clients have to manage their data in my backend themselves (e.g change their email at the client). That would mean i preferable ignore any changes to the external user data (at the provider).
Option 2 - OAuth
The client acquires an auth_code by signing in with any external provider (SiwA (ios), Google, Facebook)
The client sends this auth_code to my backend where this code is used to issue an access_token/refresh_token from the provider
The backend sends back the access_token/refresh_token obtained from the external provider
Now everytime the client does make a request it has to contain the external access_token which then is used at the backend to ask the external provider if this token is valid and the client has access to the ressource. In other words i use the external access_token for authorization
Everytime user data (e.g. email, address...) is required at the backend, it is necessary to ask the external provider for this data by providing the access_token, which was given by the client
Problems/Questions:
I assume that the refresh process has to be perfomed on client side in case the backend redirects unauthorized from the provider in case the token expires. Is that correct ?
How do i determine from which provider the token is. It seems weird for me to implement a trial and error process and just ask every provider if this is a valid token. E.g. if the backend receives an access token in the header of the request it doesnt know which provider to ask. (or should i encode this information in the header like Bearer Provider Token in order to know where to check the access token.
Using Option 2, anytime the external provider experiences downtime no user is able to use my backend, while with using Option 1 only the signin (inital sigin or after explicity signing out, which invalidates the refresh token) is not availabe for this specific provider.
Is there anything i'm missing ? It seems to me that Option 2 introduces a lot of unnecessary communication to the auth provider, while Option 1 does neglect any communication which is potentially required (e.g. sync of identity state) ?
The main question for me is, considering Option 1 which seems more suitable for my scenario, do i necessarily have to react to any state change of the user state, like change of email at the external provider or are there any downside to ignoring anything then the external user id to allow for authentication.
I ended up implementing OpenID, realizing i only needed authentication and no authorization nor rigorous coupling of user data. At the time of asking the question, i was aware of the difference, however i didn't dig deep enough into the requirements of my project. Thus i discarded the basic OAuth protocol, since i didn't need any authorization to external ressources.
Regarding OpenID, the management of external identities from the OpenID provider is not in the scope of the protocol it has to be done independently. There are other protocols and methods dealing with that e.g. SCIM.
I ended up relying on the fact the the external id provided with id_token is unique and initialize a one time mapping at the first time authenticating (basically a signup). My server manages the user data from this moment on. Subsequent authentication request rely on the fact that this mapping never changes and any user data may differ compared to any data kept at the provider, e.g. different mail addresses at my server compared to the google mail of the external identityl. However this doesn't violate my requirements.
Furthermore, i want to add that i ended up supporting implicit flow and auth code flow, which means the client can send the id_token directly, instead of sending the auth_code. I did not fully get the point why this is more unsecure since from my current perspective my server ask the provider to verify the id_token which prevents any malicious intends by proividing false id_tokens.

What is the difference between the two use cases of using OpenID Connect in Keycloak? (Client vs Application)

I am very new to the concepts of SSO and Keycloak. I am trying to read the official documentation of Keycloak. In the "Supported Protocols" part (https://www.keycloak.org/docs/latest/securing_apps/index.html), the documentation talks about the two use cases of using OIDC like this:
"The first is an application that asks the Keycloak server to authenticate a user for them. After a successful login, the application will receive an identity token and an access token. The identity token contains information about the user such as username, email, and other profile information. The access token is digitally signed by the realm and contains access information (like user role mappings) that the application can use to determine what resources the user is allowed to access on the application.
The second type of use cases is that of a client that wants to gain access to remote services. In this case, the client asks Keycloak to obtain an access token it can use to invoke on other remote services on behalf of the user. Keycloak authenticates the user then asks the user for consent to grant access to the client requesting it. The client then receives the access token. This access token is digitally signed by the realm. The client can make REST invocations on remote services using this access token. The REST service extracts the access token, verifies the signature of the token, then decides based on access information within the token whether or not to process the request."
What I do not understand is this: In the first paragraph it talks about an application making a request and in the second one it talks about a client. But aren't applications counted as clients? Why the specific differentiation? And can anyone given an example of the remote services that is talked about in the second part?
Thank you.
But aren't applications counted as clients? Why the specific differentiation? And can anyone given an example of the remote services that is talked about in the second part?
Yes exactly it. The reason for the differentiation is because there could be many applications more than just this one client. And the client, that the user is authed against may want to access all those other applications' data.
For example take the google ecosystem. Does google email have access to drive, and photos, etc... While it could out the box, it doesn't. You need to explicitly allow email "offline access" to those other applications, even though they are all part of the same platform.
Keycloak understands this and provides that terminology. But it is a bit confusing because this isn't the best way to think about it. Instead a better explanation is that there is just the user and service clients. The service clients all talk to each other and ask for a user's data. While a user may want their data by going straight to one application, other applications may want that user's data too.
Assuming you want to actually allow one service to ask for user data from another service, you want to be using something that supports authorization as a service and not just authentication. There are some examples of this, such as PolicyServer and Authress.

Do users of a third party app accessing our API's have to log in with us even if they've already authenticated with their their system?

We have a third party company developing a mobile app and they want to call our API's. Our API is protected with Identity Server 4 which uses OpenID Connect and OAuth2. In order to access our API's would their app have to pop open a mobile browser so the user can log into our system? What if users already authenticated with the third party's identity provider? Seems like that would create a negative user experience to authenticate two different times while using the app.
My understanding is we would add their app as a client in Identity Server using the authorization code grant. Would we add their identity provider as an identity provider that our Identity Server can call?
Any help on this would be greatly appreciated. I've researched myself into a hole.
would their app have to pop open a mobile browser so the user can log into our system?
You are pretty much right on your assumptions that their app would have to somehow initiate oidc flow to allow the users of the mobile app to authenticate with the authority of your API (identity provider).
Seems like that would create a negative user experience to authenticate two different times while using the app.
It seems that this is what's holding you back. Firstly, that mobile app's identity provider is separate from your API's authority and it is important to understand that the "user" authenticated with the other identity provider means close to nothing to your API because the token has been issued by a different authority and it's not even a "user" from your user base.
My understanding is we would add their app as a client in Identity Server using the authorization code grant.
Yes, but check also Authorization Code grant with PKCE which adds extra security measures.
Would we add their identity provider as an identity provider that our Identity Server can call?
Yes, you will need to do that, but this is just a start of the things you would need to do to achieve what you are looking for. Because you already have Identity Server 4 in place, I assume your systems already have an established user base, therefore if you just redirect to the external identity provider, once a user authenticates there and the token is issued back - that kinda means nothing because you don't have any kind of mapping from the user of the third party system to the user of your system.
There is pretty much nothing out of the box in Identity Server 4 that will help you with this, but one way to tackle this is to implement some sort of account linking mechanism, where the users would first have to "link" their account in your system with the account in the third party system. With account linked, you would have means to issue claims related to your system.
Identity Server 4 absolutly has out of the box solutions for this. If they didn't, what would be the point calling themselve a OAuth 2.0 framework?
You do not need to initiated a oidc flow like stated. What does that even mean anyway? oidc is connection protocol, not a flow. Flows include hybrid, implicit, clientcredential, etc.
You could obtain an access token for your 3rd party app a number of ways all use the token endpoint built into identity server 4 specifically for creating access tokens The most common is using the ClientCredential flow, where you gain a bearer token by hitting the identity server 4 token endpoint passing the client_credentials grant type with the ClientId of the client they want to access, a shared secret supplied by you, and the api scope they are attempting to access.
Another option is you could create a user for this client on Identity Server 4, then gain an access token using the ResourceOwnerPassword flow by hitting the token endpoint passing the password grant type, clientId, username, and password, again along with the api scope they want to access.
For information on how to do all of the above check out his link. It will help you on your way.
http://docs.identityserver.io/en/latest/endpoints/token.html

Why use OAuth in mobile HTML5 application that will use REST?

I am exploring the possibilities of a banking mobile HTML5 application. It will be contacting with the main server via RESTful API. Very often I hear that people are using OAuth in their mobile apps to access APIs. For example, SpringSource's html5expense demo app.
So I don't fully understand why bother? Couldn't the user just login in a standard way, receive a cookie with session id (or in case of Play framework, session data), that will be used to identify user when the app makes requests to REST?
Oauth is usually a lot more secure than most BASIC AUTH, or "logging in in a standard way" approaches (and OAuth is becoming more and more of a standard).
When you login, through most "standard" ways, the user enters his username & password, into the application, and username/password are then often either stored locally, or transferred to the application, to then potentially be relayed to a "main server" that for example provides the API. So the user will have to enter his very secret login information (e.g. for banking?), into a client, app or system he doesn't know or trust...
With OAuth, the user is directed to a login page of the owner of that API .. e.g. his bank for example, where he logs into the secure login page that he knows and is asked for his consent that the application "xyz" would like to access his data.... The application that has requested that access, is then given a token with which it can access the API without needing to know the username and password. That way the username/password is only entered once, at a location the user trusts.
Furthermore, the user could later log into and admit page .. (the bank app? or and admin frontend), and delete the given access right to the API, and so stop an application accessing his information, without having to change his password.
Beyond the effect of being actually safe, using something like OAuth, for a banking app also makes sense as it will give people more confidence if modern security techniques are applied. It makes it also feel safer.
If you are not going to publish your API to third party developers; there really is no reason to bother with OAuth.
The biggest reason OAuth exists is to enable integrations with your API without your users having to give out their username and password to a third party. Other reasons is that it makes it possible to put a time frame on third party access to resources, or to scope access.