Closed SBatais closed 5 months ago
Hello,
Quick answer, in the current implementation: No
When the IDP does not support groups or roles, as they are not present in scopes_supported, it will not add the user groups in the JWT token response during the authentication phase and even the filter fails at startup time.
In the same way, if the IDP does not supports the offline_access, it will reject the refresh token requests (also depends on the IDP implementation as some of them, even when the offline_access is omitted it accepts to refresh the token).
Can you please, describe more the issue you are facing? Does your IDP supports a claim, other than groups or roles which can identify a group of users? If yes, we can include that claim so that it can be mapped using spark ACLs.
Also, we can support working with an IDP which does not support a refresh token or for which the feature is disabled. To work seamlessly, we will suppose the IDP continually refreshes the user token to avoid user disconnection/re-authentication during navigation when the token expires. Also, the filter should redirect the user back to his current page (instead of the home page) during request for new access token.
Hello
Thanks for your reply.
Firstly here is some technical information of the used IDP and from .well-known/openid-configuration:
"grant_types_supported": [
"authorization_code",
"password",
"client_credentials",
"refresh_token"
]
"claims_supported": [
"sub",
"iss",
"auth_time",
"acr",
"sid"
],
"scopes_supported": [
"openid",
"profile",
"email",
"address",
"phone"
]
My first issue is that the groups information are not retrieved. I will come back to the IDP provider to know if the groups information are available in the ID token or/and the access token. Once the user is authenticated, I have this message in the logs where we can see the groups is empty:
{"@timestamp":"2024-05-29T11:40:11.295Z","ecs.version":"1.2.0","log.level":"INFO","message":"Successfully authenticated user (<firstname> <lastname>): email <email address> sub <id-user> (roles: [], groups: [])","process.thread.name":"HistoryServerUI-26","log.logger":"io.okdp.spark.authc.OidcAuthFilter"}
My second issue is with the refresh token, and I need to test it deeper.
regards
Ok, thanks. Form the scopes_supported seems like your IDP is configured to authenticate users only and does not include authorization claims like roles or groups. The filter can be configured, through spark ACLs to authorize the users individually but not suited from the security perspective and complex users management.
In fact, yes, you can check with the IDP provider if it's possible to add groups or roles in the client scope and assign users to these groups.
For keycloak, for example, it's possible to enable the roles, groups or any custom claims by using Mappers. These claims then will be included in the JWT access token.
Here is the reply of my IDP provider about groups:
_The groups information is return in the id_token and also in the accesstoken. Please do not forget to request the groups information by adding "groups" in the scope in your requests.
OK, This can be done using the scope parameter or AUTH_SCOPE env variable
env:
- name: AUTH_SCOPE
value: openid+profile+email+groups
....
I have already tested it, but I get this error because of the scope 'groups' not available in the supported groups of the IDP
The parameter 'scope|env: AUTH_SCOPE' contains an unsupported scopes '[groups]' by your oidc provider.\nThe supported scopes are: [openid, profile, email, address, phone]","error.stack_trace":"java.lang.IllegalArgumentException: The parameter 'scope|env: AUTH_SCOPE' contains an unsupported scopes '[groups]' by your oidc provider.\nThe supported scopes are: [openid, profile, email, address, phone]
Yes, actually the code enforces the check against the supported scopes reported by the IDP.
Your IDP reports, via the discovery endpoint, it does not support the groups
scope and that's why it fails.
"scopes_supported": [
"openid",
"profile",
"email",
"address",
"phone"
]
I have published a v1.2.1 as a pre-release to remove the enforcement. You can download the jar from there, test and let us know if it works so that we can publish this version into maven central.
I have tested with v1.2.1 and with AUTH_SCOPE="openid+profile+email+groups"
I get a warning when the scope is not in the supported_scopes list:
{"@timestamp":"2024-06-04T07:15:58.445Z","ecs.version":"1.2.0","log.level":"WARN","message":"The parameter 'scope|env: AUTH_SCOPE' contains an unsupported scopes '[groups]' by your oidc provider. The supported scopes are: [openid, profile, email, address, phone]","process.thread.name":"main","log.logger":"io.okdp.spark.authc.utils.PreconditionsUtils"}
and the groups information is retrieved once the user is authenticated:
{"@timestamp":"2024-06-04T07:20:11.748Z","ecs.version":"1.2.0","log.level":"INFO","message":"Successfully authenticated user (firstname lastname): email email_adress sub userid (roles: [], groups: [group1, group2])","process.thread.name":"HistoryServerUI-20","log.logger":"io.okdp.spark.authc.OidcAuthFilter"}
I would like to know if it's possible to do the same for the scope offline_access
The check was removed as well for the offline_access scope.
What is the error you are getting when you add the scope?
env:
- name: AUTH_SCOPE
value: openid+profile+email+groups+offline_access
...
I have also tested with scope=....+offline_access
After few hours, I get an error saying that the refresh token should not be null or blank:
{"@timestamp":"2024-06-04T11:46:52.452Z","ecs.version":"1.2.0","log.level":"INFO","message":"The user address_email token was expired, renewing ... ","process.thread.name":"HistoryServerUI-1437","log.logger":"io.okdp.spark.authc.OidcAuthFilter"}
{"@timestamp":"2024-06-04T11:46:52.453Z","ecs.version":"1.2.0","log.level":"WARN","message":"/","process.thread.name":"HistoryServerUI-1437","log.logger":"org.sparkproject.jetty.server.HttpChannel","error.type":"java.lang.NullPointerException","error.message":"The parameter <refresh_token> should not be null or blank","error.stack_trace":"java.lang.NullPointerException: The parameter <refresh_token> should not be null or blank\n\tat io.okdp.spark.authc.utils.PreconditionsUtils.checkNotNull(PreconditionsUtils.java:41)\n\tat io.okdp.spark.authc.provider.impl.PKCEAuthorizationCodeAuthProvider.refreshToken(PKCEAuthorizationCodeAuthProvider.java:153)\n\tat io.okdp.spark.authc.OidcAuthFilter.lambda$doFilter$2(OidcAuthFilter.java:218)\n\tat io.okdp.spark.authc.utils.exception.Try.onException(Try.java:34)\n\tat io.okdp.spark.authc.OidcAuthFilter.doFilter(OidcAuthFilter.java:219)\n\tat org.sparkproject.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)\n\tat org.sparkproject.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)\n\tat org.sparkproject.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)\n\tat org.sparkproject.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)\n\tat org.sparkproject.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)\n\tat org.sparkproject.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)\n\tat org.sparkproject.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505)\n\tat org.sparkproject.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)\n\tat org.sparkproject.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)\n\tat org.sparkproject.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)\n\tat org.sparkproject.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:772)\n\tat org.sparkproject.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:234)\n\tat org.sparkproject.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)\n\tat org.sparkproject.jetty.server.Server.handle(Server.java:516)\n\tat org.sparkproject.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)\n\tat org.sparkproject.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)\n\tat org.sparkproject.jetty.server.HttpChannel.handle(HttpChannel.java:479)\n\tat org.sparkproject.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)\n\tat org.sparkproject.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)\n\tat org.sparkproject.jetty.io.FillInterest.fillable(FillInterest.java:105)\n\tat org.sparkproject.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)\n\tat org.sparkproject.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)\n\tat org.sparkproject.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)\n\tat org.sparkproject.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)\n\tat org.sparkproject.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)\n\tat org.sparkproject.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)\n\tat org.sparkproject.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)\n\tat org.sparkproject.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)\n\tat java.base/java.lang.Thread.run(Unknown Source)\n"}
Ok, have disabled the offline_access in case the IDP does not support it or disabled. You can test with the new jar in the pre-release and let us know.
@idirze : where can I find the new jar ?
It's with the same name in the assets of the pre release
https://github.com/OKDP/okdp-spark-auth-filter/releases/tag/v1.2.1
I have re-tested with v1.2.1 and with AUTH_SCOPE="openid+profile+email+groups++offline_access". I don't have anymore the error "The parameter
Here are the logs when the token expired:
{"@timestamp":"2024-06-05T11:18:37.615Z","ecs.version":"1.2.0","log.level":"INFO","message":"The user _address_email_ token was expired, removing cookie and attempt to re-authenticate ... ","process.thread.name":"HistoryServerUI-26","log.logger":"io.okdp.spark.authc.OidcAuthFilter"}
{"@timestamp":"2024-06-05T11:18:40.555Z","ecs.version":"1.2.0","log.level":"INFO","message":"Successfully authenticated user (_fistname lastname_): email _address_email_ sub _userid_ (roles: [], groups: [group1, group2])","process.thread.name":"HistoryServerUI-2471","log.logger":"io.okdp.spark.authc.OidcAuthFilter"}
Thanks @idirze for your support
@SBatais, thank you for the feedback and feel free to rise any issue, contribution or any request information. We have just published the new version with the fixes in Maven Central
You can download the 1.2.1 jar from there.
So, i close the issue as resolved.
Hello
I would like to know if okdp-spark-auth-filter can work with an IDP that doesn't support the scope groups and offline_access (array "scopes_supported" in issuer-uri/.well-known/openid-configuration), and be able to get groups and the refresh token information from an access token returned by the IDP when the user is authenticated.
Thanks in advance for the reply.