ADFS 2016 - OAuth2 SPA - Get a new token silently - oauth-2.0

I have a SPA where the user authenticates in ADFS and the application gets an access token. I am trying to use JS code to simulate the functionality of ADAL JS where a hidden iframe is used to make a request to ADFS to get the new token.
This is the 'src' value of the iframe:
https://../adfs/oauth2/authorize?client_id=...&response_type=id_token&redirect_uri=...&prompt=none&domain_hint=...&login_hint=...&nonce=...
The ADFS is configured with two realms: AD and ADLDS (LDAP). Because of this I am not sure what values I need to pass on domain_hint & login_hint parameters for a user in ADLDS.
The request fails with message:
https://....html?client-request-id=...#error=login_required&error_description=MSIS9621%3a+Unable+to+handle+the+OAuth+authorization+request+without+getting+user+input.
The ADFS event viewer shows this error:
Exception details:
Microsoft.IdentityServer.Web.Protocols.OAuth.Exceptions.OAuthNoPassiveException: MSIS9233: There are multiple identity providers found for OAuth Authorization request with prompt set to none. Unable to complete home realm discovery.
Is this functionality actually supported in ADFS 2016? Any idea as to what am I doing wrong?

The prompt=none request parameter says that you want to pass the process the /authorize request without user interaction. But during its processing, there is something that needs user interaction - the server probably doesn't know which identity provider to choose, so it returns the error. If you make the same request just by pasting the /authorize URL to your browser without the prompt=none parameter, the server will probably give you a possibility to choose a provider.
You wrote you would like to get an access token, but your /authorize URL contains response_type=id_token. If you want an access token, the parameter should be response_type=token (see RFC).
Looking at the Azure doc, the domain_hint request param is supported of OpenID Connect, so your request scope parameter should contain openid value. It's also necessary for getting an ID token (if you want it).

Related

Requesting an authorization code through a backchannel

According to the OAuth2.0 spec and the way it is implemented in OpenIddict 3.1.1, an authorization code should be retrieved by performing a GET request to the authorization endpoint. This will then redirect the user to a login page (if needed) and ask for explicit authorization from the user.
It is, however, also possible to configure a client application to use an implicit consent type, where the user does not need to explicitly give permission to the application.
My question builds on this: If I know that the user is already signed in (I have a valid access token), would it be possible to request an authorization code for a different application through a backchannel POST request (using the authorization header to specify that I have access to do this) instead of having to go through the browser for this flow?
As far as I can see in OpenIddct 3.1.1, the authorization code is generated in some middleware that handles signin results. This seems to make it difficult for me to generate such an authorization code in a custom endpoint designed for my desired scenario mentioned above.
The reason I'm wondering about this at all is because I'm building a desktop application for which I'll open a browser for the initial login, but after that I need to request an authorization code for a custom server back-end and I'd prefer not having to open the browser once more just for this purpose, since I know the user is authenticated (and authorized) to request this authorization code anyway. I would of course send the all the required information in this backchannel POST request (client_id, code_challenge, challenge_method, scopes...)
EDIT:
The reason I need a second access token is because:
I have 4 systems:
Desktop application
Custom Server
Resource Server
Identity Provider
The desktop application is the one that is directly used by the user, and it will request an access token through the regular auth_code flow from the Identity Provider. This desktop application will then request resources in the resource API, for which it needs an access token. This process is working as standard.
Now I also want the Custom Server application to request resources from the resource server. Normally you would use client credentials for this, because it is server to server, but the resources are owned by the user, so I'd want an access token specifically for these resources.
For this I now start a second auth_code flow on the desktop application to request an authorization code for the Custom Server. I then send this auth_code back to the Custom Server, which exchanges it for an access token. This works, but I would prefer if I didn't have to start a full on auth_code flow on the desktop application for this second process, as I know that the user is authorized to request this auth_code, and the consent type for the Custom Server is implicit in this case.

OpenId Connect Implicit flow, how to maintain session

I am building an Angular SPA app and using Okta as an Idp. since its an SPA so I think I need to use Implicit flow. I have two queries here-
Since in Implicit flow a refresh token is not issued, does it means that th user will be logged out of the app after the token expires and he has to log in again?
Why do I need to use Implicit flow in case of SPA? why not Authorization code flow? since I have control over both the front end (SPA) and back end (REST API) . for example in case of Spring MVC architecture for the web app Authorization code flow is possible.
Thanks,
pchh
Yes, if the token expired, you have to re-autenticate. Normally you still have a valid session on the identity providers site, so you can do a "silent" login using an iframe. Libraries like oidc-client support a silent login, which can do this for you.
You need to use implicit (or hybrid) flow, when you need to access to the access token from your javascript app. With authorization code flow your javascript app doesn't get the access token, so if your API needs an access token for authorization, what are you going to send?
If your auth server supports OpenID Connect (OAuth2 extension) and single sign-on (SSO) feature, to get a new token before the old gets expired, use an iframe with a URL you used for authentication, but add prompt=none parameter (and possibly id_token_hint parameter). See OpenId Connect RFC. The prompt=none parameter tells the /auth endpoint to issue a new token(s) if the user has an open SSO session at your OAuth2 server. If not, the request will fail. There is a separate RFC for session management.
The Authorization code flow requires you to access the /token endpoint, which usually requires authentication (client ID + client secret) and you cannot keep the secret safe in a browser. For this reason, the token endpoint doesn't use to support CORS headers, so you cannot access it using XHR. Using the Auth code flow, you get a code as a redirect URL param (?code=), which gets to the server hosting your SPA (browser sends it there after redirect). The implicit flow returns tokens in hash part of the redirect URL (#access_token=), which stays in a browser (it's not sent to the server), so it's safer.

OAuth2 Sending Client secret in authorization step

I'm building a web app that uses the Oauth2.0 protocol. I have registered my app with the authorization server and received my client id and client secret.
I'm now working on Authorization part and specifically using the Authorization Code grant type. In that process i'm sending the user to the authorize endpoint with the following query parameters:code, client_id, redirect_uri, scope and state. (omitting the client_secret)
The problem that i'm dealing with is i'm getting an error back saying I need to provide the client_secret as well.
I was under the impression the client_secret is not needed at this part and shouldn't be sent in this request but rather when the client sends the authorization code (along with id & secret) to obtain the access token.
So my question is, Is it wrong (against oauth 2 protocol) that the authorization server requires the client secret to be sent in the request for the authorization code?
I am not 100% sure of this, but I did some research myself and what I found is that is not a real problem not to keep the "client secret" a secret. The only possibility of someone malicious being able to get through the Authorization specs is prevented by some facts:
1. Client need to get authorization code directly from the user, not from the service
Even if user indicates the service that he/she trusts the client, the
client cannot get authorization code from the service just by showing
client id and client secret. Instead, the client has to get the
authorization code directly from the user. (This is usually done by
URL redirection, which I will talk about later.) So, for the malicious
client, it is not enough to know client id/secret trusted by the user.
It has to somehow involve or spoof user to give it the authorization
code, which should be harder than just knowing client id/secret.
2. Redirect URL is registered with client id/secret
Let’s assume that the malicious client somehow managed to involve the
user and make her/him click "Authorize this app" button on the service
page. This will trigger the URL redirect response from the service to
user’s browser with the authorization code with it. Then the
authorization code will be sent from user’s browser to the redirect
URL, and the client is supposed to be listening at the redirect URL to
receive the authorization code. (The redirect URL can be localhost
too, and I figured that this is a typical way that a “public client”
receives authorization code.) Since this redirect URL is registered at
the service with the client id/secret, the malicious client does not
have a way to control where the authorization code is given to. This
means the malicious client with your client id/secret has another
obstacle to obtain the user’s authorization code.
// copy paste of hideaki answer
Concluding
OAuth2 specify that you need to inform your secret into a request if your application is a server-side based app (different than a single-page application or mobile) which does not make its source code available. However, if you can't control your base code, like in an native mobile application, you should look for another solution.
References
OAuth2 Documentation
Bear similar stack question
Simplifying OAuth2

HTTP requests for WSO2 Identity Server user authentication

I am writing a REST API to be consumed by our internal applications. I need to login and logout users of the identity server using code grant via http requests
presentation
I need to know how to call the following endpoints:
/authorize (invoked from server-side)
/accesstoken (invoked from server-side)
/login
/logout
CASE:
Our company has many applications. I want one point of authentication which will happen in their company-x account like how you only need to login to atlassian account to access jira and confluence cloud. The REST API I'm working is for our front-end developers (as of now).
presentation
I cannot simply let the user login to WSO2 IS since they only need a module where they can manage their company-x profile and other basic stuffs. By this I think I have 2 options:
Customize WSO2 Identity Server UI and permissions. But the problem is, I still need an endpoint to get that id_token. I am also not sure if this is the right approach.
Know how to call /authorize, /accesstoken, /login and /logout endpoint and write my own minimal required UI and provide an endpoint that will respond the id_token
How about having a basic login page on front-end and use request path authenticator to get the authorization code/id_token.
Basically what this means is instead of redirecting the user to IS login page you can extract the username and password from the basic login page you created and send the authorization grant request along with the credentials.
so your authorization code request will be:
https://localhost:9443/oauth2/authorize?response_type=code&client_id=JqB4NGZLMC6L3n4jz094FMls2Joa&redirect_uri=https://localhost/callback&scope=openid&sectoken=<sec_token>
sec_token = base64encode(username:password)
You need to add basic-auth request path authenticator in your Service Provider configurations. This request should return you an authorization code. If you want an id_token simply use the implicit flow with request path authentication.
If you use code grant type, there will be a browser redirection from /authorize to /login. I don't think you can handle that by a REST call. (You might be able to handle that by calling url in location header of each 302 response. But I don't think it's a nice way to do this.) If you want to develop a REST API, I think password grant type will be more suitable.

Prompt for AD credentials on every OAuth2 authorize request

We have an application with its own authentication, for which we recently added OAuth2 support. A corporate customer can specify the data for his ADFS or Google domain, and we use that to automatically sign up and log in their users.
Now, the problem is switching credentials. When we log out from our application, clicking the login button (which redirects to the configured ADFS OAuth2 authorize endpoint) will immediately validate the user and send him back to our app, with a valid code for his current credentials.
The Google endpoint has a special parameter, approval_prompt, which we can use to force an intermediate step, at which the user can switch his credentials. I don't think ADFS has that.
What other solutions do we have? Is it possible to configure something on the ADFS server that would prompt the user to enter his credentials for every authorize request?
Here's how those url parameters work, as best as I understand them:
wa is the operation we're requesting. So far, I've only seen two values: wsignin1.0 and wsignout1.0
wfresh has something to do with the max age of cached credentials, but I don't entirely understand it. 0 means don't use cached credentials.
wtrealm is the AppID configured in ADFS. This tells the ADFS server which app is trying to authenticate. For us, this is the base url of the app.
wctx is some app-specific data returned to the app from the ADFS server after the request. Since we're using the standard System.IdentityModel setup, it handles parsing and reacting to this value, not our code. There's an ru parameter encoded inside it. This is the return url. This is how we get back to the page we came from.
wct is the timestamp of the authentication request
For us adding the parameter prompt=login to que authorization request URL is working with OAuth2 :
/adfs/oauth2/authorize?response_type=code&client_id=XXX&resource=YYY&redirect_uri=ZZZZ&prompt=login

Resources