I’m developing my own OAuth2 + OpenID Connect implementation. I am a bit confused about how to handle OAuth flows for native (specifically, Mobile) clients. So far, I am seeing that I need to use an Authentication Code Flow. However, based on my research, there are some details that seem to contradict each other(at least based on my current understanding).
First, standard practice seems to say that mobile apps are not inherently private and, as such, standard flows that make use of a back channel should not be used. As a work around, the PKCE extension can be used (and utilize the built-in device browser as opposed to a web view so the tokens and sensitive information are less likely to be leaked).
However, under the Protocol’s Dynamic Client Registration specification, it is also mentioned that mobile apps should use this method of client registration to get a valid client ID and client secret... But, why would we do this when in an earlier section it was established that mobile applications were indeed public clients and couldn’t be trusted with confidential information like a client secret (which we are getting by using this DCR mechanism...
So, what am I not understanding? These two things seem to contradict one another. One claims mobile apps are public shouldn’t be trusted with a secret. Yet, in the recommended DCR mechanism, we assign them the secret we just established they can’t be trusted with.
Thanks.
A bit late, but hope it helps. So part of the OAuth2.0 protocol is two components, the client_id, and client secret. The client and server must agree on those two values outside the protocol i.e. before the protocol start. Usually, the process is as follows. The client communicates with the Authorization Server using an out-of-bound communication channel to get these values and be registered at the server. There is two way this client registration can happen, statically and dynamically. Statically mean the client_id and secret do change, i.e. the client gets them once when he registers with the server. Dynamic client registration refers to the process of registering a client_id every time the client wants to use to protocol, i.e. a client secret will be generated for him every time (also by an outbound communication).
Now, Why use dynamic registration?
Dynamic client registration is better at managing clients across replicated authorization servers., The original OAuth use cases revolved around single-location APIs, such as those from companies providing web services. These APIs require specialized clients to talk to them, and those clients will need to talk to only a single API provider. In these cases, it doesn’t seem unreasonable to expect client developers to put in the effort to register their client with the API, because there’s only one provider.
Does Dynamic Client registration offer any security advantages?
No, both are vulnerable if used with a JavaScript or a Native Mobile Client (JavaScript client can be inspected, and Mobile apps can be decompiled). Hence, both of them require PKCE as an extra layer of security.
Related
I have familiarity with OAuth 2.0 / OpenID Connect but am new to WebAuthn. I am trying to understand how a scenario using those OAuth flows and connections would work using WebAuthn. I thought by mapping concepts from oauth to webauthn I would be able better understand the concepts.
I think similar to how in OAuth implicit grant flow a client may receive an id_token and access_token, in WebAuthn a client may receive a credential object from the Authenticator using navigator.credential.create.
The part I do not understand is how this credential can reliably be consumed by downstream services. In OAuth a client or server may send "access_tokens" and the receiving servers may request the public keys from the authorities to validate that it hasn't been tampered, is not expired, has correct audience, etc. This relies on the authorities having a publicly available /.well-known endpoint with the public keys.
However, I think because the keys are specific to the authenticator instead of a single shared public key it is not possible to have these be discoverable.
This is where I don't understand how credentials could be consumed by services. I thought the client would have to send the public key WITH the authenticator and client data but this is 3 pieces of information and awkward. Sending a single access_token seems actually cleaner.
I created a graphic to explain visually.
(It may have technical inaccuracies, but hopefully the larger point is made clearer)
https://excalidraw.com/#json=fIacaTAOUQ9GVgsrJMOPr,yYDVJsmuXos0GfX_Y4fLRQ
Here are the 3 questions embedded in the image:
What data does the client need to send to the server in order for the server to use the data? (Similar to sending access_token)
How would sever get the public key to decrypt data?
Which piece of data is appropriate / standardized to use as the stable user id?
As someone else mentioned - where there are a lot of commonalities between how WebAuthn and something like OpenID Connect work, they aren't really useful for understanding how WebAuthn works - they are better to explore after you understand WebAuthn.
A WebAuthn relying party does not have its own cryptographic keys or secrets or persistent configuration - it just has a relying party identifier, which is typically the web origin. The client (browser and/or platform) mediate between the relying party and authenticators, mostly protecting user privacy, consent, and providing phishing protection.
The relying party will create a new credential (e.g. key pair) with the authenticator of a user's choosing, be it a cell phone or a physical security key fob in their pocket. The response is the public key of a newly created key pair on the authenticator. That public key is saved against the user account by the RP.
In a future authentication, the authentication request results in a response signed by that public key. The private portion is never meant to leave the authenticator - at least not without cryptographic protections.
This does pair well with something like OpenID Connect. The registration is normally by web domain, which means that there could be a lot of manual registrations necessary (and potentially management, and recovery, and other IAM type activities) necessary. With OpenID Connect, you can centralize the authentication of several applications at a single point, and with it centralize all WebAuthn credential management.
I thought by mapping concepts from oauth to webauthn I would be able better understand the concepts.
This seems to be working against you - you're trying to pattern match WebAuthn onto a solution for a different kind of problem (access delegation). Overloaded terminology around "authentication" doesn't help, but the WebAuthn specification does make things a bit more clear when it describes what it means with "Relying Party":
Note: While the term Relying Party is also often used in other contexts (e.g., X.509 and OAuth), an entity acting as a Relying Party in one context is not necessarily a Relying Party in other contexts. In this specification, the term WebAuthn Relying Party is often shortened to be just Relying Party, and explicitly refers to a Relying Party in the WebAuthn context. Note that in any concrete instantiation a WebAuthn context may be embedded in a broader overall context, e.g., one based on OAuth.
Concretely: in your OAuth 2.0 diagram WebAuthn is used during step 2 "User enters credentials", the rest of it doesn't change. Passing the WebAuthn credentials to other servers is not how it's meant to be used, that's what OAuth is for.
To clarify one other question "how would sever get the public key to decrypt data?" - understand that WebAuthn doesn't encrypt anything. Some data (JS ArrayBuffers) from the authenticator response is typically base64 encoded, but otherwise the response is often passed to the server unaltered as JSON. The server uses the public key to verify the signature, this is either seen for the first time during registration, or retrieved from the database (belonging to a user account) during authentication.
EDIT: Added picture for a clearer understanding of how webauthn works, since it has nothing to do with OAuth2 / OpenID.
(source: https://passwordless.id/protocols/webauthn/1_introduction)
Interestingly enough, what I aim to do with Passwordless.ID is a free public identity provider using webauthn and compatible with OAuth2/OpenID.
Here is the demo of such a "Sign in" button working with OAuth2/OpenID:
https://passwordless-id.github.io/demo/
Please note that this is an early preview, still in development and somewhat lacking regarding the documentation. Nevertheless, it might be useful as working example.
That said, I sense some confusion in the question. So please let me emphasize that OAuth2 and WebAuthN are two completely distinct and unrelated protocols.
WebAuthN is a protocol to authenticate a user device. It is "Hey user, please sign me this challenge with your device to prove it's you"
OAuth2 is a protocol to authorize access to [part of] an API. It is "Hey API, please grant me permission to do this and that on behalf of the user".
OpenID builds on OAuth2 to basically say "Hey API, please allow me to read the user's standardized profile!".
WebauthN is not a replacement for OAuth2, they are 100% independent things. OAuth2 is to authorize (grant permissions) and is unrelated to how the user actually authenticates on the given system. It could be with username/password, it could be with SMS OTP ...and it could be with WebauthN.
There is a lot of good information in the other answers and comments which I encourage you to read. Although I thought it would be better to consolidate it in a single post which directly responds to the question from OP.
How does WebAuthN allow dependent web API's to access public key for decrypting credential without having to send the key?
There were problems with the question:
I used the word "decrypt" but this was wrong. The data sent is signed not encrypted and so key is not used to decrypted but verify the signature.
I was asking how a part of OAuth process can be done using WebAuthN however, this was misunderstanding. WebAuthN is not intended to solve this part of process so the question is less relevant and doesn't make sense to be answered directly.
Others have posted that WebAuthN can be used WITH OAuth so downstream systems can still receive JWTs and verify signatures as normal. How these two protocols are paired is a out of scope.
What data does the client need to send to the server in order for the server to use the data?
#Rafe answered: "table with user_id, credential_id, public_key and signature_counter"
See: https://www.w3.org/TR/webauthn-2/#authenticatormakecredential
How would server get the public key to decrypt data?
Again, decrypt is wrong word. Server is not decrypting only verifying signature
Also, the word server has multiple meanings based on context and it wasn't clarified in the question.
WebAuthN: For the server which acts as Relying Party in WebAuthN context, it will verify signature during authentication requests. However, the server in question was intended to mean the downstream APIs would not be part of WebAuthN.
OAuth: As explained by others, theses API servers could still be using OAuth and request public key from provider for verification and token contains necessary IDs and scopes/permissions. (Likely means able to re-use existing JWT middlewares)
Which piece of data is appropriate / standardized to use as the stable user id?
For WebAuthN the user object requires { id, name, displayName }. However, it intentionally does not try to standardize how the ID may propagated to downstream systems. That is up to developer.
See: https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialuserentity
For OAuth
sub: REQUIRED. Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User
See: https://openid.net/specs/openid-connect-core-1_0.html#TokenResponse
Hopefully I didn't make too many technical inaccuracies. 😬
I have two client applications : Asp.Net MVC Core web app and an Android native mobile app, and an IdentityServer4 Server as an OpenID Server`.
I know that I have to create two client records for both of them (in the IS4's Clients table) :
a Hybrid Flow for the web app
a Hybrid/Authorization Code + PKCE for the native mobile app
But I'm wondering if I can create only one Client info for both of them or not?
I think you should create one client definition for each client, so you better can separate them and better evolve them as needed over time. Also makes it easier to separate them in the logs for example.
A question is however why/if you really need to support the hybrid flow? I think both clients only need to use the authorization code flow.
If you want to follow OAuth 2.1, then there are only two flows to use, either authorization code flow or client credentials flow. All other flows are not recommended due to various security issues. See https://oauth.net/2.1/
Tore's answer gives good reasons to keep those clients separated. If you're still not convinced, I would turn the question around - why do you want to have one logical client data used by two separate clients? This will cause some weird issues in the future. For example, at some point you might want to rate-limit one of those clients, or change client authentication method, or even block one of them completely. You will have to do it for both your apps if you don't create a separate client.
From the security point of view, there is a good reason to keep those two separated: the web client can be a confidential client with a secret assigned. The mobile client will be a public client, without a secret*. This is a solid reason not to mix those two, as you will lower the strength of your security considerably.
*In fact, best practice would be to use DCR and register a new client for each device where your app runs.
I can find plenty of example of single page apps (which can't manage a client secret) and plenty of examples of old-school server-side apps (which can manage a client secret) using OAuth.
But for us and, I suspect, the majority of enterprisey systems, a system is both server-based and client-based.
We can easily (and securely) identify the client server-side, and we could then make the resulting (user) access_token available browser-side.
The question is, does doing this introduce a risk?
The client-server (the server-side component of the client) cannot guarantee that the browser is running its code - but it can guarantee that all access to the resource owner's data on the client has been approved by the resource owner.
Thanks.
The principle itself does not introduce a risk but of course you need to take care of the method used to expose the access token to the browser. One such approach is documented here: https://hanszandbelt.wordpress.com/2017/02/24/openid-connect-for-single-page-applications/
It suggests to expose a server-side endpoint that can be called with a cookie which will then return session information that may include the access token.
I'm developing an API which only needs to be accessed by servers, as opposed to specific, human users. I've been using the client credentials grant which, if I'm not mistaken, is appropriate for this use case.
So the remote websites/apps, after registering their corresponding OAuth2 clients, are simply requesting an an access token using their client ID/secret combination, via a SSL POST request + HTTP Basic authentication.
Now I was wondering if it would be a good idea, during said access token request, to check the remote IP to make sure it actually belongs to the client that was registered (you'd have to state one or several IPs when declaring your app, then it would be checked against the remote IP of the server making the POST /token request).
I feel like this would be an easy way to make sure that, even if the client ID/secret are somehow stolen, they wouldn't be just usable from anywhere.
Being fairly new to the OAuth2 protocol, I need some input as to whether this is a valid approach. Is there a more clever way to do this, or is it straight up unnecessary (in which case, for what reasons)?
Thanks in advance
That's certainly a valid approach but binds the token tightly to the network layer and deployment which may make it difficult to change the network architecture. The way that OAuth addresses your concern is by the so-called Proof-of-Possession extensions https://datatracker.ietf.org/doc/html/draft-ietf-oauth-pop-architecture.
It may be worth considering implementing that: even though it is not a finalized specification yet, it binds the token to the client instead of the IP address which safeguards against network changes and is more future proof.
I'm starting a new system creating using .NET MVC - which is a relatively large scale business management platform. There's some indication that we'll open the platform to public once it is released and pass the market test.
We will be using ExtJs for the front-end which leads us to implement most data mining work return in JSON format - this makes me think whether I should learn the OAuth right now and try to embed the OAuth concept right from the beginning?
Basically the platform we want to create will initially fully implemented internally with a widget system; our boss is thinking to learn from Twitter to build just a core database and spread out all different features into other modules that can be integrated into the platform. To secure that in the beginning I proposed intranet implementation which is safer without much authentication required; however they think it will be once-for-all efforts if we can get a good implementation like OAuth into the platform as we start? (We are team of 6 and none of us know much about OAuth in fact!)
I don't know much about OAuth, so if it's worth to implement at the beginning of our system, I'll have to take a look and have my vote next week for OAuth in our meeting. This may effect how we gonna implement the whole web service thing, so may I ask anyone who's done large-scale web service /application before give some thoughts and advice for me?
Thanks.
OAuth 1 is nice if you want to use HTTP connections. If you can simply enforce HTTPS connections for all users, you might want to use OAuth 2, which is hardly more than a shared token between the client and server that's sent for each single request, plus a pre-defined way to get permission from the user via a web interface.
If you have to accept plain HTTP as well, OAuth 1 is really nice. It protects against replay attacks, packet injection or modification, uses a shared secret instead of shared token, etc. It is, however, a bit harder to implement than OAuth 2.
OAuth 2 is mostly about how to exchange username/password combinations for an access token, while OAuth 1 is mostly about how make semi-secure requests to a server over an unencrypted connection. If you don't need any of that, don't use OAuth. In many cases, Basic HTTP Authentication via HTTPS will do just fine.
OAuth is a standard for authentication and authorization. You can read about it in many places and learn; Generally the standard lets a client register in the authentication server, and then whenever this client attempts to access a protected resource, he is directed to the auth-server to get a token (first he gets a code, then he exchanges it with a token). But this is only generally, there are tons of details and options here...
Basically, one needs a good reason to use oAuth. If a simpler authentication mechanism is good for you - go for it.