IdentityServer - separate authentification, authorization, resources without any use of UI-websites? - identityserver4

I want to have an architecture made up of these devices / programs with different roles (which are all separated, none of these roles must exist in one and the same instance):
CLIENT
AUTHENTICATION-SERVER
AUTHORIZATION-SERVER (there can be a multitude of these)
RESOURCE-SERVER (also many possible)
And:
I don't want to use any websites a user has to navigate to.
From my studies of OAuth and Open ID Connect I would assume that a Client could get an ID_TOKEN (after authorization) from an AUTHENTICATION-SERVER and could then request ACCESS_TOKENS to different resources from the AUTHORIZATION-SERVERs.
I guess the method I described allows identity theft on the client side.
I cant find a way to easily get id tokens from an authorization server to a client (which I could then use to authenticate to multiple authorization servers). My clients are trusted. I want to use native apps and implement open id connect among them anyway.
I do not want to use any websites as of now and still need to be able to have a secure communication with associations of claims to users and everything. Are OpenID Connect and its possible 'Flows' appropiate for this? Are there any other implementations that would allow the flow I described (or mabye derivations of OpenID Connect)?

It's not recommended but if you really don't want to use a browser (which is somewhat anti-OAuth/OIDC and is full of limitations) then ResourceOwnerPassword grant type is the one you'll need to use. This will not return an id_token though, just an access_token.
id_tokens exist to support front-channel browser-based sign in flows, they serve no purpose if using the ROP grant type.
Access tokens are issued by the authentication/secure token service (IDS4 in this case) and grant the client (optionally with user consent) access to the resource. The resource then has its own authorization rules to enforce scope and user-related ACL/business rule access controls.

Related

Use Microsoft OAuth to authenticate our own operations

We have built a React web application that authenticates users with Microsoft via OAuth ( #azure/msal-browser package). Users are redirected to Microsoft auth page during signin, and then redirected back to our site once authentication has completed successfully. This is all working as expected.
However, we are in a position where we wish to add a custom PIN mechanism to protect some of our workflows. PINs will be encrypted/salted and stored in our own API, along with the existing mapping between Microsoft/Azure users and our own user state/records. In order for users to change/reset their PIN, we want to force them to reauthenticate with Microsoft before changing their PIN. I have not dealt with OAuth2 in a while, and am not entirely certain how this might be possible (since current auth workflow does not involve our server at all).
Ideally, users would navigate to the "Reset PIN" page and initiate the workflow. If possible, authentication would be handled through a pop-up (so as to not lose page state), which I think is possible as per documentation? If this is not possible, even a redirect to the same page with a specific query parameter (to indicate post-authentication) could work. The user would then be able to change/confirm their new PIN. At this point, a request would be sent to our API, including both the PIN and something from Microsoft that would allow our server to validate that the user did indeed just re-authenticate (proving they can change the PIN).
The primary sticking point is that our API must be able to verify that the user has just re-authenticated with Microsoft! One way to think about it would be that if a user gained temporary access to an unlocked authenticated workstation, they should not be able to perform restricted actions (as they do not know the PIN), nor be able to change the PIN (as they do not know the user's credentials). Yes, yes, I know physical access is effectively a compromise to any security, but this is a higher-level requirement...
I am guessing this workflow is possible, but am not certain how it might be possible. Would we use a different authentication workflow for this particular use case? Any pointers on a workflow we could investigate or use for this?
I can give you some info about how this should work. This type of flow can require a high level of extensibility in the authorization server though.
CLIENT REDIRECT
The client can send the OpenID Connect acr_values parameter, indicating the assurance levels it requires. In your case you would send two values.
CUSTOM AUTHENTICATION FACTOR
The user will perform standard authentication first, eg passwords. Then you would implement a custom second factor that uses the user identity and some custom logic to call your custom API.
ACCESS TOKENS
After authentication has completed, the authorization server will issue access tokens to the client. High privilege claims should only be included when strong authentication has been used. Some kind of scripting would be used here, that can read authentication result attributes.
API AUTHORIZATION
APIs should receive short lived access tokens. If it contains the high privilege claim, you know that your PIN requirements have been met.
CAN YOU SIMPLIFY?
It feels suspect to do your own PIN management. Can you outsource this, eg use a second factor of time based one time password (TOTP) instead? Mobile platforms such as the Google authenticator app provide tested solutions.

OpenID connect, OAuth 2.0 and UI functional permissions

We are looking at integrating our apps with Openid connect for our react based apps. We have ui and relevant permissions based on user - menus, navigations etc.
Can anyone point to spec or suggest on how do we handle such permissions in relation to openid connect or oauth. Basically how do we make this permissions available to ui, one approach is dedicated API for ui permissions again authorized by access token.
Another approach is permissions in token itself. Scope is one way of holding info, but it is for delegated access. Hence we are thinking to use multivalued custom attributes for holding roles and permissions in access token. But these permissions can also be huge sometimes and thinking hence if it is good idea to keep permissions in access token.
Any valuable pointers or any design approaches for handling ui permissions list please let know, we highly appreciate it.
The most flexible option is a custom API endpoint. An access token should hold important identity values such as these:
User ID
Roles
Company ID
Tenant ID
Country Code
Subscription level
These are claims, and are populated at runtime for each user, unlike scopes, which are fixed at design time.
Access tokens are designed only to be used by APIs, and clients should never read their payload. A good practice can be to return opaque unreadable access tokens to clients, to enforce this.
The actual permissions for a role can be looked up by the API once, then cached. This is preferable to storing large payloads in access tokens.
Finally, permissions for UIs may originate from two data sources: the identity data and your business data. The API can combine a result from both data sources, and transform the result to what the UI needs. Eg which columns are visible, which are read only and so on.

How to support multiple login scenarios in multi-tenanted Azure Active Directory (AAD)

Our application (referred to as "XYZ_App" below) is a multi-tenant SaaS application. We are in the process of making it available for Microsoft AppSource as a multi-tenanted "Web app / API" (referred to as "AppSourceXYZ_App" below).
We started our OpenID Connect implementation with endpoints pointing to “common” as per stated in the documentation when multi-tenancy is desired/required.
In XYZ_App, we added information in the system to know what AAD instance each XYZ_App tenant is associated with (using the GUID Microsoft assigned to this AAD instance, we are NOT using the "rename-safe.onmicrosoft.com" representation).
When using the “common” endpoints, we had to manually validate the issuer from the JWT to make sure it was the expected one: a user could access XYZ_App requesting access to XYZ_App’s tenant associated with contoso.onmicrosoft.com, get directed to “login.microsoftonline.com/common” to authenticate and then decide to authenticate with a user from another AAD instance (referred to as "anotherAADInstance.onmicrosoft.com" below). In this scenario, even though a user could successfully authenticate on anotherAADInstance.onmicrosoft.com, XYZ_App’s redirect URI must make sure the JWT issuer is the one from contoso.onmicrosoft.com. I’ll refer to this setup as Scenario_1.
With that scenario in mind, we thought about NOT using “common” and customize the requests going to login.microsoftonline.com on the fly; attempting to “jail” requests to be forced to authenticate against a specific AAD instance. We would still need to perform our validation in the redirect URI to make sure the issuer is the appropriate one, but we thought this approach might make our lives easier. I’ll refer to this setup as Scenario_2.
Do you envision Scenario_2 is viable in the long run or is it too short-sighted ? Based on my current knowledge of OpenID Connect, one limitation I can see with Scenario_2 is that it would become problematic to support “broker accounts” into our app.
Explanation of “broker accounts”: in our industry, some external users are allowed access to the system. Let’s say I have a company called “BrokerCo” (with their own brokerco.onmicrosoft.com AAD instance) who has 2 employees: Broker1 and Broker2. BOTH anotherAADInstance and contoso hired Broker1 and Broker2 to get broker services to perform tasks in XYZ_App; requiring XYZApp to grant them access. What is the ideal way for authentication from an OpenID Connect standpoint ? If XYZ_App were to use “login.microsoftonline.com/common” for authentication (like in Scenario_1; as opposed to “jailed” access like in Scenario_2), Broker1 and Broker2 could authenticate with brokerco.onmicrosoft.com (no AAD "External users" for anotherAADInstance nor contoso), but they would then get to redirect URI with an issuer that is different than what XYZ_App’s anotherAADInstance and contoso tenants are configured for... I feel like I’m back to square 1...
Do you have suggestions or pointers to solve this issue ?
Background context:
While playing with OpenID Connect issuers, I got the following error message:
AADSTS50020: User account 'testuser#anotherAADInstance.onmicrosoft.com' from identity provider 'https://sts.windows.net/XXXXXXXX-fake-GUID-9bZZ-XXXXxxxxXXXX/' does not exist in tenant 'XYZ Publisher' and cannot access the application 'YYYYYYYY-fake0-GUID-YYYYyyyyYYYY' in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
Thanks in advance !
Your question has multiple layers, trying to address most of them:
AppSource is about trial experiences for new users: this mean that any corporate account around the globe can potentially be an user of your SaaS application - or at least to the trial experience of your application, therefore the first thing you need to think when integrating with AppSource is how easy it has to be for a potential user to experience your app for the first time.
With that in mind, AppSource recommends that the trial of application is build on such a way that allows any user from any organization to sign-in, and therefore a multi-tenant approach for your application is the recommended setup for any application.
The single-tenant approach requires more control on your side, and for a trial experience - it means that the user cannot try your application right away because the operation you have to do on your single-tenant application is to add the user to an Azure Active Directory tenant as a guest user. This guest account will need then to wait receiving an email to accept the invitation to join to this tenant you are adding the user to then sign-in to your application.
Therefore your scenario 1 is the best scenario thinking on a trial experience in general, and also in general require less management (as you'd not need to create/ manage each individual account that needs to access your application as guest users of your Azure AD instance).
However some concerns you listed - that this scenario bringing are valid: Because you are accepting the common endpoint, you are saying basically that any user can sign-in to any tenant to your application, and this may not be desirable. In addition, the scenario you listed that a user can generate a token for any application is also valid, however, you can add additional checks to make this more secure and that any token generated by another authentication is blocked:
You can validate the 'audience' claim to guarantee that the token was issued to your application
You can eventually check the 'tid'/'iss' claims against of a list of tenant Ids in your database to see if that the user's organization is a valid organization in your application -- this would be valid for non-trial users/ organizations.
More information in this article.
About scenario '2' and broker accounts:
This scenario could be interpreted in two different ways:
Broker accounts are guest accounts of a customers' Azure AD tenant
Broker accounts are third party accounts but are not actually added as a user of anotherAADInstance or contoso AD
If your case is '1' then you're right: if your application needs to authenticate guest users that belong to another Azure AD tenant, then common endpoint could not be used directly.
If your case is '2' then what you'd need to do is to continue using the common endpoint and somewhat after the user is authenticated ask them to choose the company. I am describing this on generic terms without fully understanding this scenario. Perhaps this is not simple as you want the remote company to control this and not the user - so some additional complexities may need to be handled here.
A note is that if your scenario is scenario 1. - in theory - you can still use an hybrid approach, where you'd ask user to type the username inside the application and the company that they want to sign-in, then check if you need to validate the user against common or tenant-id endpoint, preparing the request and then sending a login_hint argument when authenticating. More information here

Oauth and scopes and its correct use

May be I am missing something here but what the point of client requesting scope?
What I mean is that when a client request a token he/she can say "I want everything" i.e. read/write/delete/update etc.
In reality, user might only have read access. So what's the point of requesting these in scopes? or its not a good practice/idea to put these in scope? If not then what do you really use it for?
I have seen in some places where it's used for Email, Username while others its used for repo:read, repo:write...
Isn't Authorization server going decide what permission the user has?
Thanks
I'm not sure if I understand your question fully but here goes. In a typical OAuth scenario, there's the:
OAuth provider - has the protected resource, issues access tokens to resource (e.g. Google)
End user - owner of resource (e.g, Google user)
Relay party - uses OAuth to access protected resource from provider on behalf of end user (e.g, some random app that does something with your google profile)
When you use the relay party's application, it needs to get your information from the OAuth provider. Most providers have different levels or "scopes" of access to the end user's information - it's usually not an all or nothing access. The relay party must define the scope of access, and ask the OAuth provider, the provider presents the scope of access request to the end user, and finally the end user can decide whether to grant the relay party that scope of access or deny it.
So without scope, how can a relay party request a granular level of access?

Can native applications make use of OS SSO login information?

If a user logs in to their computer using a Single Sign-On system such as Active Directory, LDAP, or Kerberos, is it possible for applications they run to know who they are and what system they authenticated with? Can I get enough information out of these systems to verify their identity without requiring any additional user input?
Specifically, I would like to be able to check these things:
Did they log in via a single sign-on system at all, or are they just using a regular user account on this machine?
What system did they use?
Does the system have some URI that would distinguish it from any other directory?
What is the current user's distinguished name in that directory?
Can I get some information which I can pass to another host to prove to that host that the user is who they said they are? For example, a token that can be used to query the SSO system.
I'd assume all of these things should be possible, and in fact encouraged, but I am not positive. I'm sure the method of getting at this information is
SSO (at least with Kerberos which is used by ActiveDirectoy) is based on a token. As soon as the user requests access to a kerberized system the system queries for the token and checks its validity for accessing the system. It's as good as querying for username and password. when the user did not log in with an Kerberos-account there is no tiket so no automated access.
using the token you can get the users login- name and from that you can then use that to query the SSO-backend (typically LDAP) for more information on that user.
LDAP is not an SSO-system as it is simply a storage query protocol but it is often used as backend for SSO-systems.
The problem often is kerberizing an application. for Webapps that means you have to kerberize the webserver so that that one then can handle the authentication process with the SSO-service and then pass that information on to the unferlying webapp.
Hope that answers you questions.
for more information have a look around the web for kerberos
You are really asking about two things:
Authentication: Who are you?
Authorization: What are you allowed to do?
Kerberos really only answers the first question, you need a secondary system like LDAP or Active Directory ( which is both kerberos and ldap in a single server) to answer the second.
If your system is using kerberos correctly, any user login should have an associated kerberos ticket. With this ticket, you can request "service" tickets
to prove your identity to remote servers that support kerberos. The ticket
contains your principal identity in the realm ( user#DOMAIN.NET ) that can be
used to query authorization systems.
However, the details required to get all the moving parts in that sentence working together "on the same page" so to speak can be very complex. The remote service has to support accepting kerberos credentials, it has to be either in the same realm or have a cross realm trust relationship configured.... The list
gets pretty long. Depending on your exact application environment, using all these things can be fairly trivial, or it can be next to impossible.

Resources