spring security oauth2 authorization server without any UI - spring-security

I have implemented a spring security oauth2 authorization server as a spring boot microservice. I'm trying to allow our main (non-java) application to migrate to oauth2 using this new service.
One thing I can't get around my head is how to set this up so that the authorization server never shows any UI. In particular, is there any way to have the /oauth/authorize UI hosted on our main application, but still accept proxied authorization approvals? Or does that UI need to be served directly by the authorization server?

You can create a login page in your UI app, the login will call the authentication server like:
curl -X POST -vu client:secret http://localhost:8081/spring-security-oauth-server/oauth/token -H "Accept: application/json" -d "password=password&username=user&grant_type=password&scope=read%20write&client_secret=secret&client_id=client"
You will receive a access token that will be used to access the endpoints in your resource server like:
curl http://localhost:8081/spring-security-oauth-resource/path/endpoint -H "Authorization: Bearer <Token>"

The UI for login does NOT need to be on the Authorization Server (see https://www.rfc-editor.org/rfc/rfc6749#section-4.3 Resource Owner Password Credentials Grant). This leaves it up to the client to collect the credentials and make a direct token request to the Authorization Server.
However, I don't generally recommend bypassing the AS UI as it means that each client application will have to implement a login logic and you won't get single sign-on between those client applications.

Related

Securing APIs and Keycloak

I deployed a Standalone Keycloak (KC) server and I developed one API that acts as a resource server(it is not supposed to handle login/registration of users etc) with Spring Boot. I want this API to be secured with KC JWT tokens. I expect every user coming has already obtained a JWT token. To the security configurations of my API I added the following configuration:
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/auth/realms/<REALM_NAME>.
Everything works as expected, my API is able to allow only authenticated and authorized users to call the endpoints. However, I have the following question:
As my configurations are right now, anyone who receives a token from my KC server and the issuer-uri can build another API and do her/his own stuff. How is it possible to restrict the KC server in order to be used only from APIs that I allow? E.g: my API should provide a client_name and a client-secret before it is allowed to verify a token with the issuer.
I am using spring-boot-starter-oauth2-resource-server to configure OAuth2 instead of the one that Keycloak provides. I am running Spring Boot 2.4, Spring Security 5 and Keycloak 12.0.4.

Steps: WSO2 Authentication and Authorization = Many Steps

I'm trying to give security to my APIs using WSO2 API Manager. I could achieved the configuration of WSO2 Identity Server to use an LDAP server with some users and made WSO2 API Manager to use this Identity Server as Key Manager. My questions are:
How can I configure end user to access an API? Is it needed to associate all the users to an application role in API Manager carbon?
The end users need to have two access token to access an API? One to authenticate in IS using (OAuth Client Key/OAuth Client Secret) and other to generate the access token to the API in API Manager using (Consumer Client Id/Consumer Client Secret)?
Is there any tutorial explaining all this steps and how to protect an API just for some users?
Basically, the token generation flow is different from grant type to grant type. For example, the jwt-bearer grant type that you are using to generate an access token has several steps such as,
Service provider requests the JWT from the IDP
Generating an access token from API Manager exchanging the JWT assertion.
This is because the usage of each grant type is different and using grant types depends on your security requirement.
The JWT Bearer grant is usually used in client apps, where user logs in providing user name and password and the rest are done in the application itself without any interaction with the end-user.
If you need to generate the token as the end-user, you can use the password grant type.
These are the steps that I made to configure WSO2 Identity Server and WSO2 Api Manager:
I've created a Service Provider in Identity Server and configured an OAuth/OpenId Connect. This generated an OAuth Client Key and OAuth Client Secret.
I've created an Identity Provider in API Manager, import a Public Certificate to authenticate the response from identity provider and use the OAuth Client Key as Alias to be checked by WSO2 API Manager when verifying the JWT Token.
I've created an API in WSO2 API Publisher, associated this API to an Interna/subscriber role and my end users to this role.
I've created an Application in WSO2 API Store to consume my Rest Service and subscribed my API to this Application.
I followed this article to these steps:
how-to-protect-your-apis-with-self-contained-acces
The problem are the steps to consume the Rest Service.
Request in WSO2 Identity Server to generate an access token to API Manager:
curl -u (OAUTH_CLIENT_KEY:OAUTH_CLIENT_SECRET) -k -d "grant_type=password&username=END_USER_USERNAME&password=END_USER_PASSWORD" -H "Content-Type:application/x-www-form-urlencoded" https://localhost:9443/oauth2/token
Request in API Manager to generate an access token to the API.
curl -i -X POST -u (CONSUMER_KEY:CONSUMER_SECRET) -k -d 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=IS_ACCESS_TOKEN' -H 'Content-Type: application/x-www-form-urlencoded' https://localhost:9444/oauth2/token
Request to API Manager to get the resource from API:
curl -v -H "Authorization: Bearer AM_ACCESS_TOKEN" http://172.19.0.1:8281/jwt/1.0.0/REST_API
Is there any easy way to accomplish these steps?
Please refer to the API security section in the documentation for more information on securing an API using roles, scopes, and tokens.
https://apim.docs.wso2.com/en/latest/learn/api-security/api-authentication/api-authentication-overview/
https://apim.docs.wso2.com/en/latest/learn/api-security/authorization/api-authorization/
This doc consists of information on how you can use different grant types with APIM and IS according to your requirements.

implementing other grants when only authorization code is available

I am creating web and mobile apps that reimplement an existing desktop app via the desktop apps publicly available API. This API only provides the Authorization Code Grant path for authentication, which would require me to either:
somehow securely store the client secret in the app
Implement PKCE & Implicit auth endpoints in my webserver as a pass-through to the API
Have my own auth system (via auth0 or equivalent), which the user then links to their API account
Is 2 possible, or is 3 my only real option?
Yes, 2 is possible, and is much more simple than I imagined. In the following examples Client is the web or mobile app, Server is your server, and API is the api you are trying to reach that only supports Auth Codes
for web (Implicit):
Client sends a standard Implicit request to Server
Server parses this request, then restructures it as an Auth Code request and forwards to API
API validates user login, and sends Auth Code to Server
Server sends Auth Code back to API
API returns access token and refresh
Server returns only access token to Client
for mobile (PKCE):
Client sends a standard PKCE request to Server
Server parses this request, then restructures it as an Auth Code request and forwards to API
API validates user login, and sends Auth Code to Server
Sever sends Auth Code to Client
Client sends Auth Code and Verifier to Client
Server verifies sends Auth Code back to API
API returns access token and refresh

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.

DotNetOpenAuth OAuth 2.0 Authorization Server with Password grant

We want to set up our own OAuth 2.0 authorization server based on the following roles:
Resource Server - An API built with ASP.NET Web API
Client - A web application built with ASP.NET MVC
Resource Owner - The end user
We plan to use the password grant type (Resource Owner Password Credentials Grant) such that the Resource Owner will submit their credentials to the Client, who will in turn make an Authorization Request. We want to authenticate the Client Request with Basic Authentication.
I'm struggling with how to set up an Authorization server using DNOA that supports this grant type. I've downloaded the Authorization Server sample project but this appears to be using token based grants (user authenticates directly with authorization server - in the sample, via OpenID).
When I try and make an Authorization request using fiddler I'm just redirected to the login page, so I'm assuming this sample doesn't support this grant type:
POST http://localhost:50172/oauth/authorize HTTP/1.1
User-Agent: Fiddler
Host: localhost:50172
Content-Length: 103
grant_type=password&client_id=sampleconsumer&client_secret=samplesecret&username=user&password=password
The same is true if I use basic authentication.
Any help would be appreciated. I've used DNOA with great success in the past to consume OAuth services, but am finding the documentation on setting up/configuring a server pretty sparse.
It looks like you are sending the password grant to the authorization server's authorization endpoint which is wrong. Grants should go directly to the token endpoint, which must be at a URL that the authorization server does not require an authenticated request to access (i.e. won't cause ASP.NET to redirect to the login page).
That said, it's very unusual (and discouraged) for a web based client app to ask the user for a password to another web service. The authorization code flow is by far the preferred one for the scenario you sound like you're describing.

Resources