Attaching device information to a refresh token in OpenID Connect - oauth-2.0

We have implemented an OIDC authentication/identity server using IdentityServer4 for .NET Core. This is a private solution, with all clients being known well ahead of time.
I would like to attach additional metadata to a stored refresh token for the purposes of identifying specific user devices and revoking their access when the end user or customer services user requests it. One possible approach to this is to have the authorization request from the client to the authentication server also contain additional context.
After reading the specification to some extent on this matter, two such parameters seem to exist, allowing additional context to be added during the authorization request. Are these parameters appropriate for this purpose? They are:
ACR - Authentication Context Class Reference
AMR - Authentication Methods References
AMR seems to fit my purposes, but I want to make sure this is the appropriate way to achieve what we're going for.
I'm also interested in alternatives, such as detecting devices via JavaScript, alternate channels for retrieving this information, soliciting this data from the user directly... please feel free to suggest an alternative approach.
Update: From comments below, it seems AMR are already enumerated, and not suited for this purpose.

Related

How does WebAuthn allow dependent web API's to access public key for decrypting credential without having to send the key?

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. 😬

Using Auth Tokens to grant access to a specific item

I have an application which provides authenticated users with views into data about various objects in a database. There's another application in our ecosystem that provides different views into some of the same objects, using its own permission model. We trust that other application's permission model, and would like to allow them to issue access tokens to users who haven't been authenticated through our application's usual method, so those users can only view specific objects that the other application has verified they have access to.
Rather than coming up with our own spec for the communication between these two applications, I was wondering if there's already a standard approach available via something like OpenID Connect. OIDC seems to handle most of the gnarly details we'd have to consider in a case like this, but the one aspect where it doesn't seem to fit is that its access tokens seem to be general-purpose, rather than calling out a specific object that the user has access to. It says "Here's a user who can access your application", but not "Here's a user who can access Item 123".
Is there a standard for using an access token to grant access to a specific item, preferably using OAuth 2 and/or OpenID Connect? Am I correct in assuming that using an item's ID as a scope on the access token would be an inappropriate use of OAuth scopes?
I've always found the best design for most real world apps to be like this:
OAuth 2.0 based tech identifies the user
You then lookup user details at an application level to enforce authorization
OAuth 2.0 scopes etc cannot handle things like this:
You don't have access to account 123
You don't have access to region US
So I tend to look them up from the user id in the token after login. This tends also to be much easier to extend, if for example the items and user rights in the external app grows over time.
For more concrete info see my write up on API Claims Caching.
Also here is an example of the coded algorithm in a Rest API, resulting in a claims object that can be injected into logic classes.
In your case the custom claims provider would be the external app, and you could query claims from it, for data that does not really fit well into OAuth tokens.
Just my thoughts - not sure if it will fully work for you - but I've found this to be quite an adaptable solution, which often puts responsibilities in the right places.

How can I restrict access to my rest API?

I'm developing my very first mobile application and I need advice. I created REST API in spring boot and it works great but I want to restrict access. It should be used only by my app. There is no user login it only gets data from the server.
Would be some API token enough or is there any other way how can I do this?
maybe it's a stupid question but I really need advice.
thanks
You can use these pointers -
Least Privilege:
An entity should only have the required set of permissions to perform the actions for which they are authorized, and no more. Permissions can be added as needed and should be revoked when no longer in use.
Fail-Safe Defaults:
A user’s default access level to any resource in the system should be “denied” unless they’ve been granted a “permit” explicitly.
Economy of Mechanism:
The design should be as simple as possible. All the component interfaces and the interactions between them should be simple enough to understand.
Complete Mediation:
A system should validate access rights to all its resources to ensure that they’re allowed and should not rely on the cached permission matrix. If the access level to a given resource is being revoked, but that isn’t reflected in the permission matrix, it would violate the security.
Open Design:
This principle highlights the importance of building a system in an open manner—with no secret, confidential algorithms.
Separation of Privilege:
Granting permissions to an entity should not be purely based on a single condition, a combination of conditions based on the type of resource is a better idea.
Least Common Mechanism:
It concerns the risk of sharing state among different components. If one can corrupt the shared state, it can then corrupt all the other components that depend on it.
Psychological Acceptability:
It states that security mechanisms should not make the resource more difficult to access than if the security mechanisms were not present. In short, security should not make worse the user experience.
Always Use HTTPS (This is hard)
By always using SSL, the authentication credentials can be simplified to a randomly generated access token that is delivered in the username field of HTTP Basic Auth. It’s relatively simple to use, and you get a lot of security features for free.
If you use HTTP 2, to improve performance – you can even send multiple requests over a single connection, that way you avoid the complete TCP and SSL handshake overhead on later requests.
Use Password Hash
Passwords must always be hashed to protect the system (or minimize the damage) even if it is compromised in some hacking attempts. There are many such hashing algorithms which can prove really effective for password security e.g. PBKDF2, bcrypt and scrypt algorithms.
Never expose information on URLs
Usernames, passwords, session tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them easily exploitable.
https://api.domain.com/user-management/users/{id}/someAction?apiKey=abcd123456789 //Very BAD !!
The above URL exposes the API key. So, never use this form of security.
Consider OAuth
Though basic auth is good enough for most of the APIs and if implemented correctly, it’s secure as well – yet you may want to consider OAuth as well. The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.
Consider Adding Timestamp in Request
Along with other request parameters, you may add a request timestamp as an HTTP custom header in API requests. The server will compare the current timestamp to the request timestamp and only accepts the request if it is within a reasonable timeframe (1-2 minutes, perhaps).
This will prevent very basic replay attacks from people who are trying to brute force your system without changing this timestamp.
Input Parameter Validation
Validate request parameters on the very first step, before it reaches to application logic. Put strong validation checks and reject the request immediately if validation fails. In API response, send relevant error messages and examples of correct input format to improve user experience.
You can use this as a checklist while making a rest API

How to integrate OAuth with a single page application?

When using OAuth (2) I need a redirection endpoint in my application that the OAuth-offering service can redirect to, once I have been authenticated.
How do I handle this in a single page application? Of course, a redirect to the OAuth-offering service is not nice here, and it may not even be possible to redirect back.
I know that OAuth also supports a username / password based token generation. This works perfectly with an AJAX call, but requires my single page application to ask for a username and password.
How do you usually handle this?
Most of the time, a redirect is okay even for SPA because users don't like to put their X service credentials on any other website than X. An alternative will be to use an small popup window, you can check what Discourse does. IMHO a redirect is better than a popup.
Google Some providers support the resource owner flow which is what you described as sending username and password, but this is not nice. These are the problems I see:
Asking google credentials to users in your site will be a no-go for some users.
The resource owner flows need the client_secret too and this is something that you must NOT put in your client side javascript. If you instantiate the resource owner flow from your server-side application and your application is not in the same geographically region than the user, the user will get a warning "hey someone is trying to access with your credentials from India".
OAuth describes a client-side flow called implicit flow. Using this flow you don't need any interaction in your server-side and you don't need the client_secret. The OAuth provider redirects to your application with a "#access_token=xx". It is called implicit because you don't need to exchange authorization code per access token, you get an access_token directly.
Google implement the implicit flow, check: Using OAuth2 for Client-Side apps.
If you want to use the implicit flow with some provider that doesn't support it like Github, you can use an authentication broker like Auth0.
disclaimer: I work for Auth0.
What José F. Romaniello said is correct. However, your question is broad and thus I feel any offered conclusions are just generalities at this point.
Application state
For example, without knowing how complex your application state is at the time you want to let your users log in, nobody can know for sure if using a redirection is even practical at all. Consider that you might be willing to let the user log in very late in his workflow/application usage, at a point where your application holds state that you really don't want to serialize and save for no good reason. Let alone write code to rebuild it.
Note: You will see plenty of advice to simply ignore this on the web. This is because many people store most of the state of their application in server-side session storage and very little on their (thin) client. Sometimes by mistake, sometimes it really makes sense -- be sure it does for you if you choose to ignore it. If you're developing a thick client, it usually doesn't.
Popup dialogs
I realize that popups have a bad rep on the web because of all their misuses, but one has to consider good uses. In this case, they serve exactly the same purposes as trusted dialogs in other types of systems (think Windows UAC, fd.o polkit, etc). These interfaces all make themselves recognizable and use their underlying platform's features to make sure that they can't be spoofed and that input nor display can't be intercepted by the unprivileged application. The exact parallel is that the browser chrome and particularly the certificate padlock can't be spoofed, and that the single-origin policy prevents the application from accessing the popup's DOM. Interaction between the dialog (popup) and the application can happen using cross-document messaging or other techniques.
This is probably the optimal way, at least until the browsers somehow standardize privilege authorization, if they ever do. Even then, authorization processes for certain resource providers may not fit standardized practices, so flexible custom dialogs as we see today may just be necessary.
Same-window transitions
With this in mind, it's true that the aesthetics behind a popup are subjective. In the future, browsers might provide APIs to allow a document to be loaded on an existing window without unloading the existing document, then allow the new document to unload and restore the previous document. Whether the "hidden" application keeps running or is frozen (akin to how virtualization technologies can freeze processes) is another debate. This would allow the same procedure than what you get with popups. There is no proposal to do this that I know of.
Note: You can simulate this by somehow making all your application state easily serializable, and having a procedure that stores and restores it in/from local storage (or a remote server). You can then use old-school redirections. As implied in the beginning though, this is potentially very intrusive to the application code.
Tabs
Yet another alternative of course is to open a new tab instead, communicate with it exactly like you would a popup, then close it the same way.
On taking user credentials from the unprivileged application
Of course it can only work if your users trust you enough not to send the credentials to your server (or anywhere they don't want them to end up). If you open-source your code and do deterministic builds/minimization, it's theoretically possible for users to audit or have someone audit the code, then automatically verify that you didn't tamper with the runtime version -- thus gaining their trust. Tooling to do this on the web is nonexistent AFAIK.
That being said, sometimes you want to use OAuth with an identity provider under you control/authority/brand. In this case, this whole discussion is moot -- the user trusts you already.
Conclusion
In the end, it comes down to (1) how thick your client is, and (2) what you want the UX to be like.
OAuth2 has 4 flows a.k.a. grant types, each serving a specific purpose:
Authorization Code (the one you alluded to, which requires redirection)
Implicit
Client Credential
Resource Owner Password Credential
The short answer is: use Implicit flow.
Why? Choosing a flow or grant type relies on whether any part of your code can remain private, thus is capable of storing a secret key. If so, you can choose the most secure OAuth2 flow - Authorization Code, otherwise you will need to compromise on a less secure OAuth2 flow. e.g., for single-page application (SPA) that will be Implicit flow.
Client Credential flow only works if the web service and the user are the same entity, i.e., the web service serves only that specific user, while Resource Owner Password Credential flow is least secure and used as last resort since the user is required to give her social login credentials to the service.
To fully understand the difference between recommended Implicit flow and Authorization Code flow (the one that you alluded to and requires redirection), take a look at the flow side-by-side:
This diagram was taken from: https://blog.oauth.io/introduction-oauth2-flow-diagrams/

Client-server user authentication

UPDATE: I failed to mention earlier that we want solution that will be flexible with authenticating users from within our databases or by asking other servers to tell us if the user is authenticated. It is also worth mentioning that these other servers are not under our control so we can't enforce a specific user model.
I had a long and hard read on OAuth and OpenID but they are both not a suitable solution for our situation and will make the process harder to the user. This is something that has been solved a thousand times, yet I cannot find the solution.
What we are looking for is a framework that can be used in a REST services server to authenticate users (no third-party clients involved) with their username and password.
The solution must not pass the username and password except the first time on login and use tokens for further authentication. Even though OAuth does use tokens, it is designed to allow third-party clients access to the service-providers resources. That is not the case here, the services are for our own application only, the only thing needed is user authentication.
What do you guys think is the most appropriate solution?
Configuration:
-Spring server that provides RESTful services with our thinking going towards using Spring Security with some user management and token management framework.
-iOS Device that will be making HTTPS calls to the server.
What we ultimately want is to have the device send a login request and receive a token if the login was successful, later on make requests using that token. Just like Facebook, excluding third-party involvement.
Is there something that is ready to be configured in our server? Or should we consider building our own token management, comparison and generation software?
Is using Spring-Security with an iOS application without involving storing cookies or redirecting to pages possible?
OpenStack offers as part of it's many projects related to open source cloud... the project Keystone. Which does this pretty much exactly what you want.
You might want to check it out here:
http://docs.openstack.org/developer/keystone/

Resources