Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

request information when groups and offline_access scopes not supported #16

Closed
SBatais opened this issue May 28, 2024 · 16 comments
Closed

Comments

@SBatais
Copy link

SBatais commented May 28, 2024

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.

@idirze
Copy link
Contributor

idirze commented May 29, 2024

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.

@SBatais
Copy link
Author

SBatais commented May 29, 2024

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

@idirze
Copy link
Contributor

idirze commented May 29, 2024

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.

@SBatais
Copy link
Author

SBatais commented Jun 3, 2024

Here is the reply of my IDP provider about groups:

The groups information is return in the id_token and also in the access_token.
Please do not forget to request the groups information by adding "groups" in the scope in your requests.

https://idp_provider_address/oauth2/authorize?client_id=client_id&redirect_uri=https://spark-history-address/home&response_type=code&scope=openid+profile+email+groups

@idirze
Copy link
Contributor

idirze commented Jun 3, 2024

OK, This can be done using the scope parameter or AUTH_SCOPE env variable

Example configuration:

env:
- name: AUTH_SCOPE
  value: openid+profile+email+groups
....

@SBatais
Copy link
Author

SBatais commented Jun 3, 2024

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]

@idirze
Copy link
Contributor

idirze commented Jun 3, 2024

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.

@SBatais
Copy link
Author

SBatais commented Jun 4, 2024

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"}

@SBatais
Copy link
Author

SBatais commented Jun 4, 2024

I would like to know if it's possible to do the same for the scope offline_access

@idirze
Copy link
Contributor

idirze commented Jun 4, 2024

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

@SBatais
Copy link
Author

SBatais commented Jun 4, 2024

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"}

idirze added a commit that referenced this issue Jun 4, 2024
@idirze
Copy link
Contributor

idirze commented Jun 4, 2024

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.

@SBatais
Copy link
Author

SBatais commented Jun 4, 2024

@idirze : where can I find the new jar ?

@idirze
Copy link
Contributor

idirze commented Jun 4, 2024

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

@SBatais
Copy link
Author

SBatais commented Jun 5, 2024

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 <refresh_token> should not be null or blank", and it seems that the automatic re-authentication is working fine, without any action from the user.

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

@idirze
Copy link
Contributor

idirze commented Jun 6, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants