Nexus OSS Remote User Token (RUT) for SSO - single-sign-on

Hello I am using Nexus OSS, and wanted to simulate SSO, using Remote User Token. Currently the Nexus is configured to LDAP authentication, and is working fine.
As per the instructions found here https://books.sonatype.com/nexus-book/reference/rutauth.html
Basically enabled Remote User Token and added header field Name "REMOTE_USER". This user is ldap and has access.
This instance is behind apache, so from apache, To test this RUT, I can set the header value REMOTE_USER, whoever, I don't see passed in user getting logged nor I see cookie being generated. I even tried firefox rest api client and set header, but with the same results. I can see that HTTP header is being set right.
Am I missing something?
Is there a way to debug that? Appreciate any help.
Thanks
S

RUT handles authentication, but the authenticated user still needs to be authorized to access the web UI. What this means is that you need an LDAP user or group mapping in Nexus which assigns the necessary roles and privileges to the user.

I had a similar issue with Nginx, the header was not set using the correct value.
This can be quite confusing, as the reverse proxy does not complain and simply sends a blank request header to Nexus.
Using Keycloak and Nginx (Lua), instead of a preferred_username field in the IdP response:
-- set headers with user info: this will overwrite any existing headers
-- but also scrub(!) them in case no value is provided in the token
ngx.req.set_header("X-Proxy-REMOTE-USER", res.preferred_username)
I had to use the preferred_username field returned in the response's id_token element:
-- set headers with user info: this will overwrite any existing headers
-- but also scrub(!) them in case no value is provided in the token
ngx.req.set_header("X-Proxy-REMOTE-USER", res.id_token.preferred_username)

Related

Why does the PayPal API not recognize my client id and secret

The Paypal API doesn't recognize my Client ID and Secret I got from https://developer.paypal.com/developer/applications/
I wanted to include a server side checkout according to this tutorial https://developer.paypal.com/docs/archive/checkout/how-to/server-integration/
When I do the request to https://api-m.paypal.com/v1/payments/payment I always get a 401 Error with the message "Authentication failed due to invalid authentication credentials or a missing Authorization header.".
I checked multiple times if my credentials were correctly included into the request. I also tested the endpoint in my server environment and as well via Postman.
I also tried the route https://api-m.sandbox.paypal.com/v1/oauth2/token to exchange my credentials with an access token and got the same problem.
I also tried to create multiple Sandbox and Live Accounts and always got the same error.
Has anyone an idea what the problem could be?
There are two separate issues here.
You first need to use /v1/oauth2/token to obtain an access token, and then use that access token to call any of the other actual APIs.
The credentials you obtain from PayPal Developer will be for either "Sandbox", or "Live". Make sure you choose the correct tab (sandbox, for development). Sandbox credentials will only work for api-m.sandbox.paypal.com , and Live credentials will only work for api-m.paypal.com . The two environments are completely separate.
If you still have issues, post the SANDBOX client ID and secret you are using, and the full request and response to the api-m.sandbox.paypal.com endpoint. There should be a PayPal-Debug-Id in any error response, in the headers if nowhere else.

Why does Keycloak admin-cli client receive 403 Forbidden for listing groups?

We're using keycloak-admin-client-12.0.4.jar to obtain groups via GroupsResource.groups, and receive an HTTP 403 Forbidden when doing so on one of our environments (it does work on another). 403 seems to mean that the secret we use for the admin-cli client is OK, but somehow, the admin-cli client is not allowed to list groups (I also tried with a wrong secret and got 401 in that case).
Now we're trying to verify that the admin-cli client is correctly configured on that environment to allow this.
To our surprise, it's not at all obvious how this is configured, or whether it's configurable at all. The admin-cli client that is pre-configured in a vanilla Keycloak Docker image doesn't have any roles assigned, so how does Keycloak know what it is allowed to do? Is admin-cli maybe hardcoded into Keycloak with certain rights? And if so, why would we be receiving a 403 then?
It turns out that in the "Clients / admin-cli" view, in the tab "Service Account Roles", one has to select something in the drop down "Client Roles" in order to see what is configured, while intuition would say that this would change the configuration instead of only reading it. In the dropdown, we had to select "realm-management", revealing a lot of "Available Roles", out of which we had to add "manage-users" to the "Assigned Roles."

Keycloak server authentication

I'm creating Java appliation, where I will need users to log in. Currently I'm verifying if I can configure Keycloak safe enough. I'd like to make sure my application is really authenticating users against my Keycloak server - eg I know there is something like DNS Poisining or other attacks, where my application could get to attackers server with duplicated/attackers Keycloak instance. What surprised me, I have currently configuration with follwing keys:
keycloak.auth-server-url=...
keycloak.realm=...
keycloak.resource=...
keycloak.public-client=true
keycloak.security-constraints[0].authRoles[0]=..
keycloak.security-constraints[0].securityCollections[0].patterns[0]=...
keycloak.principal-attribute=preferred_username
and no public key is needed. Even worse here: https://stackoverflow.com/a/40516696/520521 I see upvoted comment telling, my application may download key from (malicious) server.
Are there any extra steps I need to follow, to authenticate Keycloak server before starting to authenticate users against it?
Based on your configuration, it seems that you've defined your client in Keycloak as public. This allows your client to be able to call Keycloak without any authentication. This type of client is used for example when you're going to authenticate via js in webpage in which nothing can be hidden from attacker as they have access to the source of the page.
If you set the "Access Type" of your client to "confidential" (in Client Settings on Keycloak Admin UI) and save the settings, there will appear another tab (next to "Setting" tab of the client) titled "Credentials". There you can see the default secret that is created for your client. You should then put this secret as below in your keycloak.json file inside your application:
"credentials": {
"secret": "paste-the-secret-value-here"
}
You can also re-generate the value by selecting the "Regenerate Secret" button.
You can also change the "Client Authenticator" there and set it to "X509 Certificate". Then you would be asked to define a regular expression to validate the "Subject DN" of the certificate that client will be using for authentication. Any certificate matching that regex would be considered as valid and authenticated. Then you have to setup your client to use such certificate instead of defining the "secret" value in the keycloak.json file.
There is of course another option which uses "Signed JWT" which is also secure and you can find the details about how to set it up in Keycloak documentation at Client Authentication section.
I can't see a word that this is the aim, but seeing where public and private key is placed I understand that answer is, that in realm settings -> keys -> active there is list of keys. You may download public key or certificate with button on right side. In my case of Spring boot, enter application.properties file a public key under keycloak.realm-key.

Keycloak authentication: how can a external user get an token without exposing client secret

I have a query about how keycloak is supposed to be working with client without GUI access.
Basically I have:
A keycloak server configured with a realm, clients(Access type confidential) and Users
A server application with a GUI that also provide API, secure with keycloak (client, user, blablabla)
This is kind of working already as I am able to log on the GUI, have the redirect, etc..
Even accessing the APIs works well, when I have access to a GUI: I log on my UI, follow the redirect and get my UI to display the token. The the human (to differentiate the user from an application), can use the token in any API client.
In this context the user never sees the client secret, which is instinctively the right way. (note that I am very opened to people telling me my instinct is wrong!)
What I am NOT able to do so far is to find the way a server application (without GUI) can get a valid token?
The authorization_endpoint, as far as I understand it, requires both the client id and the client secret) to get a token, which I would rather avoid: I don't think giving my client secret to all my "customers" is the proper way to do it.
Alternatively I could create an API on my client that woudl ask for user credential and ask for the token in its behalf, but that would expose the clients credentials to my application, which is against the whole concept!
I tried setting my client Access type as public, but when I use the API call below I also get a error:
POST /auth/realms/realmname/protocol/openid-connect/tokenAPI
'grant_type=client_credentials'
'client_id=client_id'
'username=username'
'password=password'
{
"error": "unauthorized_client",
"error_description": "Public client not allowed to retrieve service account"
}
Would anyone know how this is supposed to be done ?
Thanks in advance.
Max
(...) A server application (without GUI) can get a valid token... typically using the Client Credentials flow.
But we would define in this case a dedicated Client for your server (client?) application to authenticate against. The returned token (not bound to a specific user) will serve for authorizations on allowed applications (i.e. your classic GUI or API clients).
So, basically you should (in very short):
define a specific confidential Client in your Keycloak
add the desired applications (or other Clients) to the Client Scope(s). Those you want to authorize transitively from this Client.
authenticate against this Client with Client Credentials flow (given the token endpoint, client id, credentials, scope)
ensure that you are authenticating through TLS and that parameters are included in request body (and not in headers - for enhanced privacy)
further harden security of your Client(s)
When you do not want anymore this particular server (client?) application to access your applications, you can change the corresponding "authentication" Client's secret/credentials or simply delete it.
"I don't think giving my client secret to all my "customers" is the proper way to do it."
You are right and the proposed method above strictly avoids that. Each customer would have its own credentials.
EDIT
(adding more details)
By performing as above, you would end up with the following scheme:
Flow Keycloak Server
C/S app. or Customer X <--- Client Creds ---> Auth. Client X
--- Access Token ---> Appl. Client <--> Appl. Server
C/S app. or Customer Y <--- Client Creds ---> Auth. Client Y
--- Access Token ---> Appl. Client <--> Appl. Server
Browser users <--- Standard ------> Appl. Client <--> Appl. Server
Note: this is not a detailed flow chart. Arrows mostly show relationships here.
Finally, please note that the terminology may differ a little here, but the proposed method is basically the same that Google uses. So you may aswell take some inpiration from there:
https://developers.google.com/identity/protocols/oauth2
I just had the same problem some weeks ago
In my case, I have a backend API and a frontend application that the users can use.
Eventually, I can't share the client_secret to the frontend application.
So here is my solution:
On keycloak, create a client (ex front_end_client) with grant type public
This client is going to be used by the frontend application to authenticate users using implicit flow (with PKCE will be more secure)
On keycloak, create a second client (On the same REALM as the first client) with grant type confidential, this client is going to be used by the backend API
Now, this is how it works:
Frontend app authenticate users and get the access token (Using the font_end_client)
The frontend app sends this token for every request to the backend
Backend app verify this token, and can retrieve permissions from it

Keycloak integration with Pingfederate

What I want to do is this:
I have keycloak integrated with my application. So when my app is launched , keycloak login page is shown to user. Now , I am trying to provide an option to login with PingFedrate. So a button to login with PingFed appears(once a new SAML provider is configured in keycloak). On PingFedrate I tried to integrate SP inititated SSO:
I added a new SP connection and there I configured it as SSP initiated SSO. (It forced me to configure SOAP Authentication , where I selected basic and configured random username password). Then I downloaded metatdata.xml from this SP and imported in keycloak which autofilled the login url as : https://myserver:9031/idp/SSO.saml2 (i.e. without client id). After this when user clickon Login with PingFed - PingFed gives following error:
Unexpected System Error Sorry for the inconvenience. Please contact
your administrator for assistance and provide the reference number
below to help locate and correct the problem.
I found the solution to this.
Firstly, we need to add SP inititated SSO in Pingfed for keycloak.
Secondly, the reason I could not make SP inititated SSO work was that keycloak's entityId should be same as Pingfed SP connection's Partner's Entity Id / Connection Id.
Keycloak, by default keeps entity id equal to url of keyloak server containing your realm. E.g
https://(keycloak-server)/auth/realms/(realm-name)
(and I could not find a way to change it through Keycloak UI)
You need to enter this URL in Pingfed.
To avoid adding this manually, you can download the keycloak config from download export tab of identity provider.
And on Pingfed , import this file.
On a side note, though I was importing it earlier, I was changing value of Partenr id to some other name as I was not aware of above restriction until I started decoding the SAML tokens in request.