Keycloak - Didn't find publicKey for specified kid - spring

I have an application divided into frontend and backend services. The frontend has public acces, while the backend is confidential. When I'm trying to authorize to get response from my backend I'm getting the following error:
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-length: 0
date: Fri, 06 Dec 2019 09:16:16 GMT
expires: 0
pragma: no-cache
vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
www-authenticate: Bearer realm="my_realm", error="invalid_token", error_description="Didn't
find publicKey for specified kid", Bearer realm="my_realm", error="invalid_token",
error_description="Didn't find publicKey for specified kid"
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
Here's my configuration for both services:
Backend:
keycloak:
auth-server-url: http://localhost:8081/auth
realm: my_realm
resource: your-client-id
ssl-required: external
credentials.secret: your-client-secret
Frontend:
sso: {
url: 'http://localhost:8081/auth',
realm: 'my_realm',
clientId: 'your-frontend-client'
}
I'm using keycloak 7.0.1 along with Spring Security.
Am I missing any additional config for allowing authorization from public client?

You have to check multiple things
You need to check your client names are same in you application and keycloak.
Sometime Keycloak URL may incorrent it should be http OR https://<IP ADDRESS>:PORT/auth
Sometime its becuase of certificate as well
Please check the version of keycloak running and client jars you are using.
https://medium.com/#siweheee/keycloak-a-real-scenario-from-development-to-production-ce57800e3ba9
Keycloak: missing realm public key
Keycloak invalid_token Didn't find publicKey for specified kid
If you are using docker environment
KeyCloak must to be accessed from all clients by the same public
address for security reasons. This includes also the GUI server. It is
not possible to talk to Keycloak via a local IP address as the
security depends on the IP address.
https://github.com/hobbit-project/platform/issues/18

Related

Setting spring.jpa.open-in-view=false makes API responses inconsistent, giving 500 error to client

Since I started working on a spring-boot application, I use to see the following warning during service startup
2022-09-20 17:59:49.061 WARN 10776 --- [ main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
To address this, I recently added the spring.jpa.open-in-view=false in application.properties file to disable this warning and it worked.
However, after doing so, some of the endpoints became inconsistent in sending the response! For instance:
User-1 requesting an endpoint gets HTTP/1.1 200 response w/ JSON body
User-2 requesting the same endpoint gets HTTP/1.1 500 response w/o any body
Ideally, both the requests should fetch a JSON response body having list of Objects (different objects based on user)
In chrome's network tab, I see the following response for User-2
HTTP/1.1 500
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 820
Date: Tue, 20 Sep 2022 12:43:55 GMT
Connection: close
There are no warnings, errors, exceptions of any sorts logged in the server log. From the start of the function execution till the returning of response, all the logs seen are expected ones.
The same User-2 making the same request when spring.jpa.open-in-view=true will fetch the following response (and 5 Objects in the list).
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 20 Sep 2022 12:52:04 GMT
Is there any related configuration that needs to be done along with spring.jpa.open-in-view=false setting?
Also, should I really need to worry on changing the default value? How will this setting impact the application?
My environment info:
Java: 1.8
MySQL: 5.7
Spring-Boot: 2.1.2.RELEASE
Spring Tool Suite: 3.9.9.RELEASE
All the queries are in #Query annotation in extended JpaRepository interfaces.
application.properties:
logging.level.org.springframework.web = INFO
logging.level.org.hibernate = INFO
logging.level.my.packages = TRACE
spring.jpa.hibernate.naming.physical-strategy = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.url = jdbc:mysql://localhost:3306/dbname
spring.datasource.username = username
spring.datasource.password = password
I'm trying to understand the reason behind this unexpected behavior. Any info could be helpful.
Thanks

Slack's files.delete API always returns cant_delete_file error

I am trying to write a script to delete old files from my Slack workspace.
Following the Slack API docs, I created an app, gave it the channels:join, channels:manage, channels:read, files:read, and files:write scopes, and installed it in the target workspace.
My app can list channels, join a channel, and list files in that channel, but whenever I try to delete a file, I get a response that looks like this:
DELETE https://slack.com/api/files.delete?token=xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx&file=Fxxxxxxxxxx
User-Agent: PostmanRuntime/7.24.1
Accept: */*
Cache-Control: no-cache
Postman-Token: 8f6854b4-794c-4685-892c-c9fafc03827e
Host: slack.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
HTTP/1.1 200 OK
date: Sat, 09 Jan 2021 19:23:28 GMT
server: Apache
x-xss-protection: 0
pragma: no-cache
cache-control: private, no-cache, no-store, must-revalidate
access-control-allow-origin: *
strict-transport-security: max-age=31536000; includeSubDomains; preload
x-slack-req-id: 227ef4f9bb4c85c42d6f1c7fb33ddac0
x-content-type-options: nosniff
referrer-policy: no-referrer
access-control-expose-headers: x-slack-req-id, retry-after
x-slack-backend: r
x-oauth-scopes: files:read,files:write,users:read,channels:read,channels:join,channels:manage,remote_files:write
x-accepted-oauth-scopes: files:write
expires: Mon, 26 Jul 1997 05:00:00 GMT
access-control-allow-headers: slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid, x-b3-sampled, x-b3-flags
vary: Accept-Encoding
content-encoding: gzip
content-length: 59
content-type: application/json; charset=utf-8
x-envoy-upstream-service-time: 26
x-backend: files_normal files_canary_with_overflow files_control_with_overflow
x-server: 10.128.70.109:80
x-via: envoy-www-iad-kyvf, haproxy-edge-iad-2ql3
x-slack-shared-secret-outcome: shared-secret
via: envoy-www-iad-kyvf
{
"ok": false,
"error": "cant_delete_file"
}
According to the API docs for the files.delete endpoint, cant_delete_file means:
Authenticated user does not have permission to delete this file.
I can only assume that this is because my user is a bot, and is not the user who originally uploaded the file.
Because I am the workspace admin, I expect that I would be able to list and delete all files if I were to authenticate with my user credentials, but the Basic App Setup docs don't say how to authenticate with user credentials, even though they contain language suggesting that some actions may require a User Token:
If you need to act as a specific user (for example, posting messages on behalf of a user, or setting a user's status), you'll need a User Token.
Is anybody aware of how to either:
Delete a file when authenticated with an App Token; or
Obtain a User Token from within an app?
Although it isn't clearly documented, App Tokens are not allowed to delete files that were uploaded by other users.
In order to do this, the App needs to be installed into the workspace via OAuth, granting the app a User Token that inherits the permissions of the user who installed it.
If that user is the workspace administrator, the app will be able to delete any file, regardless of who uploaded it. See https://api.slack.com/legacy/oauth for details

Authentication unsuccessful error even after right username and password passing in "HTTP Authorization Manager"

HTTP/1.1 401
X-message-code: PWD_WRONG
WWW-Authenticate: Basic realm="SAP HANA Cloud Platform"
Transfer-Encoding: chunked
Date: Fri, 18 Oct 2019 11:06:40 GMT
Server: SAP
Set-Cookie: BIGipServerl4097iflmapavrhcip.factory.customdomain=!Nu8jU3HA2IxyvHz2sXeD7QV2Vba36noiDcfL3aW4P6aJ3bFLqxzKN/NcLEGyHmjUFAx3qBE6h10zBwU=; path=/; Httponly; Secure; httponly; secure
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Some times, the site may encode the password at the frontend and then send it to the server which can decode it. Check with your dev team if the password is encoded by a javascript before being sent
Logically X-message-code: PWD_WRONG indicates that you provided wrong password. Double check your credentials in the HTTP Authorization Manager, it might be the case you made a typo, even characters which are not visible like whitespace or line break matter.
Looking into Create new user on Cloud Integration thread:
The message displayed (PWD_WRONG) means the member has never logged into the SCP Account and no credentials were provided to it.
Also looking here it might be the case you need to supply an appropriate client-side certificate

Spring Boot: RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"

I get the following exception when I POST the login credentials for my Spring Boot app.
org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"
It is posting to /dologin and then redirecting to /home with the jsessionid appended to the end. It does also set the session cookie too. I did not change any session settings and there is no mention of session in application.properties.
I tried to set
server.servlet.session.cookie.http-only=true
server.servlet.session.tracking-modes=cookie
As mentioned in https://stackoverflow.com/a/31792535/148844, but it didn't work.
I added
#Bean
public ServletContextInitializer servletContextInitializer() {
return new ServletContextInitializer() {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
SessionCookieConfig sessionCookieConfig=servletContext.getSessionCookieConfig();
sessionCookieConfig.setHttpOnly(true);
}
};
}
But now it just POSTs, sets the cookie, and redirects back to the login screen. It's as if it can't access the session.
I set server.session.tracking-modes=cookie (instead of server.servlet...) and it is only using cookies now, but the Chrome browser is not sending the cookie back to the server after login! /home action will only re-display the login page if user attribute in the session is null.
POST /dologin HTTP/1.1
Host: localhost:8080
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
Referer: http://localhost:8080/home
HTTP/1.1 302
Set-Cookie: JSESSIONID=3B82AAA40CE94FF490FBF7B4DBD837DD; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Location: http://localhost:8080/home
GET /home HTTP/1.1
Host: localhost:8080
Upgrade-Insecure-Requests: 1
Referer: http://localhost:8080/home
HTTP/1.1 200
Set-Cookie: JSESSIONID=B60BF649068F7E85346691FD2F5D119B; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Content-Length: 2742
Date: Sat, 29 Sep 2018 17:41:55 GMT
Notice the cookies are different and Chrome did not send the cookie back to the server? Why?
Spring Boot 1.5.13, Chrome Version 69.0.3497.100 (Official Build) (64-bit)
OK changing server.servlet.session.cookie.http-only=true to server.session.tracking-modes=cookie and changing http://localhost:8080 to http://127.0.0.1:8080/ worked. I found this answer:
Chrome localhost cookie not being set
It seems Chrome keeps flipping from allowing localhost to disallowing localhost. It was working about a month or three ago. localhost is working for a Rails app and Chrome is sending the cookies.
In fact, Chrome is also sending the _mt_rails_session Rails cookie for localhost to the Spring Boot app, but never the JSESSIONID cookie.
I suspect, but have not confirmed, it may be due to setting up HTTPS on port 8080 for an unrelated 3rd Spring Boot app, and there may be some HSTS setting cached in Chrome internals. It's probably a bug in Chrome.

Spring Security sessionID as token configuration

I am implementing a login process using Spring Security + Spring session to build login functionality for a REST like backend service that needs to create/mantain a session.
I am not sure if I am approaching the solution the right way since I am using a custom endpoint to create the session manually. Maybe the session creation needs to be done in the Authorization method itself? Or maybe there is a way to have spring create the session after some request validations in the backend? I am using a custom filter and provider for this.
Also with my current configuration, I am having an issue since the backend API is creating a new session with every request, even when it should return 401.
The requirements of this solution is as follows:
The clients will login to a third party authentication/authorization provider. Once validated, the provider will issue an access token.
The API must validate the client's access token with the third party provider. Once validated, the API must create a session and return a new token (or sessionID) to the clients.
Future calls to the API should include the token (or sessionID) in the header/cookie so the API gets the session of the client.
The big question here is: Is there a common approach to follow for using token based authentication linked to a user session? If so, what if I need to do custom validations before having spring session create the session, and also add custom attributes to this session?
My code is located here: https://github.com/munilvc/api-session/tree/master/src/main/java/com/munilvc/poc/security
For instance, some sample executions:
1) Execute custom login:
$ curl -X POST http://localhost:8080/app-api/login/createsession -v
> POST /app-api/login/createsession HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200
< x-auth-token: 15a06ce8-5b34-401a-a05f-a0d933926245
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 29 Aug 2017 01:28:24 GMT
<
171{"username":"username1"}
2) Call another endpoint with provided x-auth-token:
NOTE the x-auth-token is refreshed in the response. (means a new session is created - This is what we want to avoid, this also happens when response is 401)
$ curl -X GET http://localhost:8080/app-api/accounts/2 -H "x-auth-token:15a06ce8-5b34-401a-a05f-a0d933926245" -v
> GET /app-api/accounts/2 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.1
> Accept: */*
> x-auth-token:15a06ce8-5b34-401a-a05f-a0d933926245
>
< HTTP/1.1 200
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< x-auth-token: 42a5db80-e5e1-4127-bd85-e468af4a8fb2
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 29 Aug 2017 01:29:08 GMT
<
870{"id":3,"name":"Account 3"}
PS: I am not sure if I am allowed to provide a link to the code in stack overflow. If not, I can paste the code here as well.
Thank you very much!
Based on your requirements, OpenID Connect can be used to authenticate the end-user and authorize a client which will then receive an AccessToken. Then the AccessToken may be used to call the back-end API's (Resource Servers).
Take a look at this sample/guide on how to setup login within Spring Security 5 against an external OAuth 2.0 or OpenID Connect provider. This will meet your requirement for logging into the application using an external provider and creating a secure session within Spring Security.
Now that you are logged in to the application and the client has an AccessToken, the client can use that AccessToken in the request (Authorization Header) to call the back-end API's (Resource Servers). The Resource Server should be setup to validate the incoming AccessToken. Take a look at this sample (master and jwt-support branches) on how to configure a Resource Server.
I would strongly recommend becoming more familiar with OAuth 2.0 Authorization Framework and OpenID Connect Core 1.0.
Good luck!

Resources