using third-party identity provider with Azure AD and MSAL.js - oauth-2.0

I have created a Single Page Application with Angular and authentication/authorisation is managed by Azure AD. I have used MSAL.js to initiate the implicit flow.
Everything is working fine, but now my client wants to use her own identity provider (IDP) so that users have a single point of entry for all apps (including mine). This IDP is not mainstream, it is built in-house by the client;
I want to keep using Azure AD to manage authorisations (groups, roles...). I also want my application and its dedicated backend API to be registered in Azure AD, not in the third-party IDP.
Azure AD should remain responsible for providing the Access Token to the SPA in order to call the API.
Somehow, I should redirect the user to the third-party IDP login form and upon successful login it will redirect to my SPA, which should then associate the tokenID with an AzureAD account and retrieve the Access Token (I suppose I will have to create an account in Azure AD for users identified in the third-party provider)
However I'm having a hard time figuring out how to achieve this and if it is at all possible ?
What would be the recommended approach for this scenario ? Can I still use MSAL.js or do I have to rely on something else ?

ARCHITECTURE
Your goals are completely correct and you should not need to change a single line of code to integrate a new IDP - so you can continue to use MSAL.js.
PREREQUISITES
In order to integrate their own IDP into your system you need to insist on certain prerequisites:
The client needs to provide a Standards Compliant Identity Provider
Typically the IDP needs to communicate with your Authorization Server (Azure AD) via either Open Id Connect messages or SAML2P messages
A home grown IDP may not meet these prerequisites in which case you need to explain to the client that they need to get standards compliant.
HOW FEDERATION WORKS
Your UI will redirect to your AS
The AS will redirect to the IDP, when given a trigger
The user will authenticate in the IDP
The IDP will post a token to your AS to identify the user
The AS will issue another token to your UI
Note that there is no coding involved here - there is only standards based integration between vendor systems.
WHAT THE CLIENT WILL GIVE YOU
Client details are often supplied by giving you their metadata document, and these details are then configured in Azure AD as a trust entry:
The entity id of the IDP
The token signing public key for IDP tokens, so that your AS can validate them
A URL to redirect to
WHAT YOU WILL GIVE THE CLIENT
A similar trust entry will need to be configured in the client IDP so that it trusts requests and issues tokens - though no certificate is usually needed here:
The entity id of the AS
A URL to post tokens to
TRIGGERING THE REDIRECT FROM THE AS TO THE IDP
One option is to forward the entity id to the authorization server in Open Id Connect redirects. Often an 'idp' query parameter is used, something like this:
Client accesses your app with a bookmarked URL:
https://app.mycompany.com?idp=urn:client.com
You add an extra parameter to the Open Id connect redirect to tell it where authentication should happen:
https://login.mycompany.com/authorize?client_id=XX&idp=urn:client.com
AZURE AD SPECIFICS
Once you understand the high level process there is some technical stuff to configure the connection and you'll need to consult vendor documentation, such as this Microsoft Azure B2B article.
PRACTICE
If you haven't done this before then you need to invest some time to get a connection working and then document the process.
You can use Windows Server and ADFS to simulate a client connection, then integrate it as a SAML2P connection. There is a learning curve though, and you'll need infrastructure such as ADFS certificates.

Related

Is it okay to use client credentials grant type for authentication of a WEB API going to be consumed by SailPoint(IAM)

I have an old windows application written in VB.NET with SQL server backend. Currently the new user additions, deletion, adding entitlements etc. are managed by an old approval workflow system. After getting approvals, the user details and entitlements are inserted in to the SQL server database table manually.
I am trying to integrate this application with the SailPoint's Identity and access management. So the new user addition, deletion update and adding entitlements etc will be done through Sailpoint. For this, I would require to create a WEB API which can be called by Sailpoint and expose the functionalities(add user/delete user/add entitlements). The only consumer to this API is SailPoint.
I am new to OAuth and below are the grant types that I came across. But not sure which one I should be using in this particular scenario.
1.Implicit Grant
2.Resource Owner Password Credentials Grant
3.Client Credentials Grant
4.Authorization Code Grant
I have done research on the different authentication methods that we can use to secure the web api. But still confused on which one to apply in this scenario as this new web api is going to be made available in internet.
I already tried developing a POC with the OAuth 2.0 with password grant type referring this article. But when I read articles in the internet I found that the password grant type is not that secure and is deprecated.
Could you please advise on which grant type(client credentials/authorization code/implicit) to use in this scenario. I believe authorization code is used when the user is directly trying to access the API. In this scenario, SailPoint will be calling the API in the backend programmatically when they insert a new user in their UI.
I think it's a good approach to use client credentials in this case because the communication between IIQ and your Web API can be considered an API-to-API communication, I mean, IIQ is acting on behalf of itself in this communication.
See this article for more details - https://dzone.com/articles/four-most-used-rest-api-authentication-methods (bold part by myself)
OAuth 2.0 provides several popular flows suitable for different types
of API clients:
Authorization code — The most common flow, it is mostly used for
server-side and mobile web applications. This flow is similar to how
users sign up into a web application using their Facebook or Google
account.
Implicit — This flow requires the client to retrieve an
access token directly. It is useful in cases when the user’s
credentials cannot be stored in the client code because they can be
easily accessed by the third party. It is suitable for web, desktop,
and mobile applications that do not include any server component.
Resource owner password — Requires logging in with a username and
password. In that case, the credentials will be a part of the request.
This flow is suitable only for trusted clients (for example, official
applications released by the API provider).
Client Credentials —
Intended for the server-to-server authentication, this flow describes
an approach when the client application acts on its own behalf rather
than on behalf of any individual user. In most scenarios, this flow
provides the means to allow users to specify their credentials in the
client application, so it can access the resources under the client’s
control.

SSO for IdentityServer4 with grant type "authorization_code"

We're in a scenario where a single page application that we develop ourselves (AngularJS front end with https server APIs in the back) opens another
web application developed by a partner of ours in a new browser tab, and where this second web application needs access to a https server API that is also developed by us.
After looking around for possible solutions, we have now created a proof of concept using IdentityServer4, where the second web application is configured as a client with "authorization_code" grant type. When all applications are running on the same domain, the third party application is able to access our https server API without being prompted for user id and password.
The implementation of the second web application in this proof of concept is very much like the solution presented by bayardw for the post
Identity Server 4 Authorization Code Flow example
My question now is:
When - in production - the second web application no longer shares domain with our application and our https server API, will a call from the second web application be prompted for username and password when accessing our http server API?
Seems, you are missing some major things. First of all any API should never ask for username and password. Instead your app(s) should put a token into each request and API should validate that token. Where the user credentials should be asked is when a user accesses your (or 3-rd party) web application. Then Identity Provider creates an Identity token (usually to be persisted in a cookie and used within the app) and access token (to be provided to APIs). Each token is issued for specific Client (app) pre-registered in IdP. Probably when been hosted at the same domain your two apps shared the identity cookie and Client Id what is not correct. In production scenario you have to register the apps separately. All the rest should work fine (if you follow the routine i briefly described at the beginning).
Chosing to post an answer myself from feedback through other channels:
This boils down to the session tracking of the IdP. If cookies are being used to track IdP session, the behavior is impacted by whether a session cookie or a persistent cookie is used.
In general, I have found that Robert Broeckelmann has great articles on medium.com.

Can I use Resource owner password flow with SPA?

I'm trying to implement authentication/authorization in my solution. I have a bunch of backend services(including identity service) under API Gateway, "backend for frontend" service, and SPA (React + Redux). I have read about OAuth2.0/OpenIdConnect, and I can't understand, why I shouldn't use Resource owner password flow?
A client ( my backend for frontend server ) is absolutely trusted, I can simply send users login/password to the server, then it forwards them to Identity server, receives the access token && refresh token and stores refresh token in memory(session, Redis, etc), and send the access token to SPA, which stores it in local storage. If SPA will send a request with the expired access token, the server will request a new one using refresh token and forwards the request to API Gateway with the new access token.
I think in my case a flows with redirects can provide worth user experience, and are too complicated.
What have I misunderstood? What potholes I'll hit if I'll implement authentication/authorization as I described above?
OAuth 2.0 specification's introduction section gives one key information on the problem it tries to solve. I have highlighted a section below,
In the traditional client-server authentication model, the client
requests an access-restricted resource (protected resource) on the
server by authenticating with the server using the resource owner's
credentials. In order to provide third-party applications access to
restricted resources, the resource owner shares its credentials with
the third party
As a summary what OAuth wants to provide is an authorization layer which removes the requirement of exposing end user credentials to a third party. To achieve this it presents several flows (ex:- Authorization code flow, Implicit flow etc.) to obtain tokens which are good enough to access protected resources.
But not all clients may able to adopt those flows. And this is the reason OAuth spec introduce ROPF. This is highlighted from following extraction,
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application.The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viable.
According to your explanation, you have a trust relationship with client. And your flow seems to be work fine. But from my end I see following issues.
Trust
The trust is between end user and the client application. When you release and use this as a product, will your end users trust your client and share their credentials.? For example, if your identity server is Azure AD, will end users share Azure credentials with your client.?
Trust may be not an issue if you are using a single identity server and it will be the only one you will ever use. Which brings us the next problem,
Support for multiple identity servers
One advantage you get with OAuth 2 and OpenID Connect is the ability to use multiple identity servers. For example, you may move between Azure AD, Identityserver or other identity servers which of customer's choice (ex:- they already use on internally and they want your app to use it). Now if your application wants to consume such identity servers, end users will have to share credentials with your client. Sometimes, these identity servers may not even support ROPF flow. And yet again TRUST become an issue.!
A solution ?
Well I see one good flow you can use. You have one front end server and a back-end server. I believe your client is the combination of both. If that's the case you could try to adopt authorization code flow. It's true your front end is a SPA. But you have a backend you can utilise to obtain tokens. Only challenge is to connect front end SPA with back end for token response (pass access token to SPA and store other tokens in back-end). With that approach, you avoid above mentioned issues.

Authorisation with Azure API Management and oAuth2

I have a WebAPI (A) hosted on Azure protected by Azure B2C (B) which is being called by a mobile app (C) - this is all working correctly.
I now want to allow third parties to access my API via API Management on the same platform but I am getting extremely confused with authentication and "audiences".
The API Management developer portal has been configured as per the Azure documentation so that when the developer makes test calls on the portal it prompts for authentication using the B2C domain (B). To do this it uses an application registered against the B2C domain.
However when I want to implement the API from a third party system (D) I need to allow the system to impersonate a user when calling my API (A) so that operations happen in the context of an authenticated user on the domain (B).
I know B2C does not yet support "On Behalf Of" as a valid flow so I use hellojs to obtain an access token on the client which I pass to the third party system API via a custom head which it then appends as an Authorization header to it's call to the API.
The API Management product expects a "subscription key" to identify the products the third party implementation can use.
Does this mean with regards to the authentication part that every third party system using my API would use the same oAuth "audience" id and therefore the same Active Directory app?
It makes more sense to me that each third party implementation would have a different app on Azure Ad but that would mean my Web API would need to recognise a huge number of audience ids and redirect uris?
Finally, how do i "hide" the Web API endpoints from public use - surely use of the audience id would allow people to circumvent the API Management product?
Apologies if I have mixed any terminology up.
1) Does this mean with regards to the authentication part that every
third party system using my API would use the same oAuth "audience" id
and therefore the same Active Directory app?
They will use the same resource/scope id (i.e. audience) e.g. https://yourwebapiAppIDURI/Read but they would all have their own application IDs.
2) It makes more sense to me that each third party implementation
would have a different app on Azure Ad but that would mean my Web API
would need to recognise a huge number of audience ids and redirect
uris?
Yes they should register their applications as clients to your B2C Auth server.
The 3rd party apps should be setup in the AAD portal to have delegated access to your web API (. "Access yourwebAPIname"). If your web API exposes any scopes access to those can be delegated too.
Now when they start the token request by redirecting the user to your Auth Server, they should provide their client id and a resource/scope value of your web APIs App ID URL e.g. https://yourwebapiAppIDURI/Read.
That should result in a token with:
aud value of the Application ID associated with https://yourwebapiAppIDURI/
scp value of Read
OK, so B2C doesnt use consent:
Azure AD B2C does not ask your client application users for their consent. Instead, all consent is provided by the admin, based on the permissions configured between the applications described above. If a permission grant for an application is revoked, all users who were previously able to acquire that permission will no longer be able to do so.

OpenId connect (OAuth 2): How does look the flow when Resource Owner is not the end user (SSO)?

I would like to provide some standarized SSO mechanism in my application (some different clients, growing number of services in the backend). I am wondering if OIDC/OAuth 2 is the right tool for it.
In all examples I have seen, end user is the Resource Owner and it grants permissions (or not) to some external apps by redidericting to a page asking for permissions.
My use case is different, I want to use OAuth inside my system (for apis, web pages etc.): resource owner is i.e. some service with database (plus administrator who have access to it), end user tries to get some resources from the system. User cannot grant anything, he can be granted. I think it's the most classic scenario, which can be named Single-Sign-On. Is there any standard flow for this in OAuth 2 (or preferably OpenId Connect)? Is it achievable? Or am I looking at a wrong tool?
OIDC/OAuth can be used for both consumer as well as enterprise scenario's. The consent steps of OAuth are useful in consumer oriented scenario's. When dealing with enterprise scenario's like yours, there's no point in asking consent since it is implicit, at least for the enterprise's apps. That is certainly covered by OAuth/OIDC: the Authorization Server is not required to ask for consent and can (typically) be configured to skip that step for particular Clients. So: using OpenID Connect without consent would be suitable.
For your usecase you can use combination of OpenID Connect and OAuth Client_Creds flow. For example suppose you have a HRMS application which needs to get the employee data to show to the employee from some DB.
Register HRMS with OPenID Provider
Register HRMS as Client to OAuth Server (OpenID Server and OAuth Server can be same)
When User comes to HRMS application:
a. Check for Id_token cookie, if not present then redirect to IDP
b. IDP authenticates and if successful redirects back to SP with ID token
c. If token is valid then SP sets the token as cookie in the browser using another redirect to itself but to the home page
Now All processing will be server side:
a. HRMS app hits the IDP to get the User Data
b. If successful then it hits the OAuth Server to get the access_token
c. if successful then it uses the access_token to talk to DB Service and
get the data
SP=Service Provider, IDP = Identity Provider
Actual flow can be a little different based on security considerations.
Hope this makes it helps.

Resources