Authenticate in Identity with an external login page - identityserver4

So, we are developing a public rest api that is protected by our own Identity server through an authorization code flow. Somewhere in the middle of the flow, we also implemented a consent step (with a different web app) to grant the Api access to some data that belongs to a user's account of another web app of our own. Currently, the consent page is protected by OpenIdConnect, which login page is implemented in the Identity server itself. However, we want expose as little as possible of the Identity server to the public.
With that in mind, is it possible to implement a login page outside of the Identity server that can still authenticate the user in identity and grant the consent? If so, how?

I will start with just explaining the flow.
When an app redirects a user to Identityserver, they come to authorize endpoint to validate the request.
When request is not valid, that triggers an error.
When request is valid and user is authenticated (has auth cookie) they just go back to the client app with the code.
When request is valid and the user is not authenticated, the next redirect would be to login page. It is the place to check the credentials, set the cookie (for the Identityserver app) and redirect back to the authorize endpoint to go further with consent or final redirect to the client app.
Is the answer crystal clear already? Login page is almost the only vitally needed for Identityserver to make possible setting the auth cookie for any further SSO.
Nevertheless you can delegate the login handling to an external app (one more Identityserver instance?). In that case your front login app will perform the steps (1-2-3-4), set the first level cookie, redirect back to the client Identityserver app, which will set the second level cookie on external auth callback action and finally redirect to the original caller. Is this the scenario for you? Possibly so. The original explanation is a bit uncertain.

Related

Azure AD MSAL in iframe

I have a website protected by azure ad and uses msal, i want to access it in iframe, but it looks it does not work. Is there a way to make it work ? Is it related to the redirect url or other issue ?
You cannot authenticate the user inside iframe meaning you cannot use redirect APIs for user interaction with the identity provider.
You can start with creating your own customer page and allow the user to enter the credentials and then authenticate the user. When the user enters their credentials and clicks on login, the server will return OK (if email/password is correct). After that you should save the token in localstorage and then set isAuthenticated = true.
If you are using the Auth code flow, then you should do the authentication in the outer real page not inside the iframe. Then you will have to login once your authenticated. The concept is that you must fully redirect to the Auth pages in azure ad not in iframe.
You can achieve single sign-on between iframed and parent apps with
the same-origin and with cross-origin if you pass an account hint from
the parent app to the iframed app.
Learn more here
You need to specify in the auth config to allow redirects in IFrame
https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_browser.html

How to use an Azure AD SSO access token to sign in on another website on a new browser

I have set up an AAD SSO enabled website A that gets an access token once the user logs in. Now, the user has the option to navigate to website B, but on a new browser that doesn't have access to the session of the browser that website A was opened.
Is there a way for website B (.NET MVC Azure hosted Web App) to be setup to accept the access token (for example: through headers) to authenticate the user and establish a newly AAD SSO logged in user on the new browser? (Users can't re-enter their credentials)
In my opinion, access tokens enable clients to securely call protected APIs, so it should be stored in backend. More often we use refresh token and access token at the same time to prevent the access token expiring.
On the other hand, if I have entered the credentials in one browser, then the identity platform knew the request came from me because some information would stored in my cookie of the website, but if I used another browser to visit IDP, it was impossible to let IDP know the request came from me, because I can't share cookie infomation with different browsers.
I find 2 videos on introducing SSO, I think they will help, here is the link.
Hope it will do some help.

React multiple subdomain auth with jwt

We want develop few different services (React Apps) with the same users database and Rest API.
Some users might have access to APP 1, some for APP 2, some for both depends on their role.
We decided to go on multiple subdomain apps method.
We want SSO so only one page/app to authenticate all the apps and not a local login component for each app. using JWT mechanism in our backend.
STRUCTURE:
AUTH FLOW:
There are two main problems in this flow which are marked as 1 and 2:
Lets say i go to the login app and log in, getting accestoken from the backend.
How do i deliver the token to app1.company.com? should react login APP redirect with token in url param?
local storage is subdomain scoped.
iframe has problems with Safari.
I don't wanna save jwt in cookies for now because the flask REST can serve non-browser retailed clients.
Lets say the user want to go to app2. if we aren't able to share the token from app1 with iframes or any other method, then this app should be redirected to login and make the process again as app1, which is fine for us.
But is this really the way? if token is invalid anymore and we get Error from backend, should we redirect to the login app in the other subdomain (embed the url we wanna go back to after login success)?
Can i just use 3rd party Open id connect service?
Should i consider microfrontends approcah to make the all the "apps" on the same domain?
How "Attlassian" as an example handles this process?
What am i missing and what is the best way to solve this flow?
Lets say i go to the login app and log in, getting accestoken from the backend. How do i deliver the token to app1.company.com?
It is not a problem that login.company.com delivers the token as a parameter in the URL, because the site can verify the authenticity of the token by verifying the digital signature or with a specific endpoint in the central authentication domain. This is how openid/oauth2 does it using the "implicit" flow, although they also allows to send the token as POST, or use a 2-step flow ("authorization_code" flow)
Lets say the user want to go to app2. if we aren't able to share the token from app1 with iframes or any other method, then this app should be redirected to login and make the process again as app1, which is fine for us. But is this really the way?
You can share the token between domains using an internal iframe, but in your case I would recommend that each domain use its own token.
if token is invalid anymore and we get Error from backend, should we redirect to the login app in the other subdomain (embed the url we wanna go back to after login success)?
Yes, in the number 2) of your drawing, just redirect from app2.company.com to login.company.com and follow the same flow as in 1). You will need some type of cookie on login.company.com to avoid requesting credentials from the user again
Can i just use 3rd party Open id connect service?
Yes, you can use an external OpenIdConnect service, or deploy at login.company.com an OpenIdConnect server like IdentityServer or KeyCloak
Should i consider microfrontends approcah to make the all the "apps" on the same domain?
It is not necessary having a central authentication domain
How "Attlassian" as an example handles this process?
I don't know exactly how Attlassian does it, but currently most web services support OpenIdConnect

How to implement code grant flow in REST API?

I am developing web application in React and Django(Rest Framework)., i want to users can login with google account.,
I approach i followed is implicit grant flow.,where i get the access token in the front end., and sent the access token to the back-end. then the back-end should verify the access token with google., and return the new jwt token for future requests. once the user logged out., same cycle continues.,
By My client don't want repeat the same implicit grant flow for other devices(mobile for example)., they want authentication to be handled entirely by back-end. so i am planning to use code exchange flow.
the approach i am planning.
user clicks the login with google button
send the request to django back-end, get the clientId and server callback URL.
client redirect the request to google with the client id and callback url.
google ask permission to users and sends the access token to backend.
In the above approach the connection between client and server is broke in step 3., how to we know the back-end got the access-token. user logged in?

Identity Server 4 / OpenID Connect default redirect URL

I'm getting started with Identity Server 4 (under ASP.NET Core) using the Implicit flow to secure an Angular 2 front end (to Web API services).
Using the oidc-client JS library, I can successfully redirect from the sample's default page to my login page, have the user authenticate, then redirect (via /connect/authorize) back the the Angular site's callback.
If a user browses directly to my authentication login page (rather than the Angular home page), I can then authenticate, but have nowhere to redirect to. If I redirect manually to the auth server's /connect/authorize page, the OIDC Client reports "No matching state found in storage". (Presumably, the OIDC Client is persisting something locally to verify the response against the original request?).
An obvious solution is for the Auth server to redirect any requests without a redirect specified to the Angular client, which could then redirect back to the Auth server as normal. That feels like a lot of round trips though.
Yes - because this is not how it works. The authentication flow starts at the client application - not the identity provider.
An OpenID Connect provider typically has more then one client - so it needs contextual information (aka a valid OIDC authorize request).
If you want that the journey starts at the provider you need to do something like you proposed - but once you have a 2nd client you need to be smarter about that (e.g. a selection screen etc).

Resources