HTTP requests for WSO2 Identity Server user authentication - oauth-2.0

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.

Related

How to replace .formLogin() with .httpBasic() in spring-security-oauth2-authorization-server

In our case we need password credentials grant type, but since it is removed from both OAuth 2.1 specification and spring-authorization-server implementation I want to use the default AuthorizationGrantType.AUTHORIZATION_CODE authorization grant type but with some tweaks due to out case.
Instead Login form I want to use Basic auth since token will be requested by gateway service and we also will be secured outside and actually instead username+password we will use just username. So I need to avoid Login page since user will not see it and I have only machine-to-machine request.
The problem is that simply changing .formLogin() to .httpBasic() doesn't work. If I follow default pipeline with url in a browser then basic login form popup and after submitting credentials it shows up again and nothing happens. In the postman if I send same get request to /oauth2/authorize I just got 401 status code. If I authenticate with some another endpoint and then try to call get on /oauth2/authorize again I will get 400 instead of 401 but that's all.
So could someone help me with using httpBasic or suggest other ways to get token without getting Login page just with REST requests.
httpBasic is not OAuth2. Password flow is weak, reason for it to be abandonned. It is also a poor user experience compared to SSO solutions that serious authorization-server offer now a days.
If you want to authenticate a robot in its own name (not on behalf of an authenticated user), use client credentials flow, it does just that: authenticate (as itself) a program you can trust to keep a secret actually secret (running on your infrastructure and not in a browser somewhere on the internet)
If it is users that you want to authenticate, just have your clients use authorization-code flow (for Angular, with angular-auth-oidc-client, or an equivalent for your client(s) framework(s))

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.

Federate authorization requests with Spring Authorization Server

I'm looking to leverage the spring authorization server (https://github.com/spring-projects/spring-authorization-server).
I need to federate authorization requests to backing IDPs based on a set of rules. Is there some documentation or suggested entry points to where this could be implemented?
Rules could include:
By domain of the user name (first.last#some-domain.com)
By relying party client id
IDP hint query parameter as part of authorization request
EDITS BELOW - providing more detail and context to the problem:
Many applications will interact solely with the Spring authorization server via OIDC to authenticate users. Some users may have their credentials managed by a separate authorization server, e.g., google or facebook. In these cases, I would like to federate the authentication via OIDC to the specific identity provider.
Example Workflow:
Application --oidc--> Spring Authorization Server --oidc-> Google
There could be many ways that we could determine:
If we need to federate authentication
Which IDP to federate authentication to
We will support authorization code grant for user-driven OAuth flows. So every authentication request will start with a call to the authorize endpoint.
For example:
http://auth-server:9000/oauth2/authorize?response_type=code&client_id=messaging-client&scope=......
After this request, I'd like to configure the Spring Authorization Server to make the determination of where to federate the authentication if required.
potential options:
Have the user enter their username, then federate to an associated IDP
Look at a query parameter hint. For example: /oauth2/authorize?client_id=messaging-client&idp=google
Please let me know if I can clarify anymore.
See the Federated Identity sample.
While I don't have an example of all of the possible ways you could detect which 3rd party IDP to direct the flow to, this branch does have one example: Look at a query parameter hint. See the FederatedIdentityAuthenticationEntryPoint for an example of how to do this.
The idea is that once the /oauth2/authorize endpoint is requested via the browser, an unauthenticated user will be asked to authenticate, which triggers the AuthenticationEntryPoint. This is where we would probably want to detect the hint, or take any other action to initiate the appropriate flow or login page. Since the client_id is also usually available in that request, you could have multiple ways of responding to this request depending on your needs.
It's best to have a fallback though, so that the server responds in the "default way" when any of these mechanisms cannot proceed for whatever reason, so the implementation delegates to LoginUrlAuthenticationEntryPoint and redirects to a login page. This also happens to allow you to combine form login with federated login!

OAuth 2.0 on REST API with Third party provider

I`m new to OAuth 2.0 and am trying to develop a application using a third party OAuth provider with Authorization Code grant flow as ny Authorization Server and Spring Security.
This provider gives me two endpoints /authorize and /token and those two, after the user authorizes its access, will return a access token.
So far, I have secured the "/" endpoint, so the application redirect the user to the authorization page and then, in the callback endpoint, store the token so it can be validated by a filter in each request.
But, as the application is mainly a set of REST API's, we want to be able to test it using Postman, with that said, on Postman, I am getting the token by setting the Authorization as OAuth 2.0 and requesting the token directly from the third party endpoints but, as Postman have its own callback URI, my application doesn`t store the token generated.
So, my two questions on this are:
Using /callback endpoint to store the token and validating it before each request by a filter is the common way of doing it?
To use Postman, should I create an endpoint for storing the token generated outside the application context or should I create an Authorization Server of my own as an additional layer on top of this third party AS?
Since your application is a set of REST API's, you need to make it as a Resource Server (in terms of OAuth2).
Resource Server doesn't perform authentication itself, it only validates a token from Authorization header (Resource Server in a nutshell).
You can find an example in Spring Security samples: oauth2resourceserver
I eventually come to the conclusion that I was using Postman wrong the whole time.
So, by the end, we got the Token saved on the database when the user logs in and, then, return it to the caller, whether it is the Front-end application, or Postman itself.
Then, in every call to the API's, the caller should include the token as Authorization on the header and a Filter on Spring will check the token against the Database.

ADFS 2016 - OAuth2 SPA - Get a new token silently

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

Resources