Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

External Jupyter Notebook

Distinguishing between browser and non-browser requests

With OAuth2 enabled, when an unauthenticated user tries to access or perform an action against ModelOp Center using an external Jupyter notebook, they will not be allowed to do so until they authenticate. The trigger for the authentication logic, located in the jupyter-plugin repository, is a 401 Unauthorized status code. However, Spring Security configured as OAuth2Login is no longer sending a 401 Unauthorized, but instead a 302 Found status code. To override the 302 Found status code, we introduced the CustomAuthenticationEntryPoint class. The purpose of this class is to inspect all requests for protected resources coming from an unauthenticated user, and to determine if a 302 Found or 401 Unauthorized status code should be returned.
We identify external Jupyter notebook requests (non-browser requests) by checking for the Accept header and its value. If a request is coming from an external Jupyter notebook (non-browser request), then the Accept header will not contain the text/html value, in which case we return 401 Unauthorized. Otherwise, we return 302 Found and redirect to the login page.

To enable the use of CustomAuthenticationEntryPoint class, include the following line in the odg-gateway-service repository SecurityConfig class:

Code Block
http.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint(URI.create(this.authenticationFailureRedirectUri)));

Accessing OAuth2 configuration

...

Discovering OAuth2 configuration for external integrations

ModelOp Center has a mechanism that allow external integrations to retrieve dynamically their OAuth2 configurations.

This mechanism is available at:

http(s)://MODELOP_CENTER_HOST/api/oauth2/.well-known-configuration. This endpoint is used by all ModelOp OAuth2 clients to retrieve generic and client specific information such as authorization URI, client id, response type, scope, and redirect.code

Sample global response:

Code Block
languagejson
{
"name": "modelop",
"issuerUri": "https://authorization.server",
"authorizationUri": "https://authorization.server/as/authorization.oauth2",
"tokenUri": "https://authorization.server/as/token.oauth2",
"userInfoUri": "https://authorization.server/idp/userinfo.openid",
"userNameAttribute": "sub",
"jwkSetUri": "https://iauthorization.server/pf/JWKS",
"introspectionUri": null
}

For example, to retrieve common OAuth2 configuration, execute a GET request to /api/oauth2/.well-known-configuration. To retrieve Jupyter client specific information, execute a GET request to If a given external integration needs to fetch specific custom configurations, then it can perform a request appending its OAuth2Client id, this will return any existing configurations related to that clientId.

Sample request for jupyter

GET http(s)://MODELOP_CENTER_HOST/api/oauth2/.well-known-configuration/jupyter where jupyter is the OAuth2 client id.code

If existing configurations were found, then a response similar to the next one will be returned:

Code Block
languagejson
{
"clientId": "jupyter",
"scopes": [
  "openid",
  "profile",
  "email"
],
"redirectUri": "http://modelop.center/jupyter.html",
"responseType": "token",
  "oAuth2Provider": {
    "name": "modelop",
    "issuerUri": "https://authorization.server",
    "authorizationUri": "https://authorization.server/as/authorization.oauth2",
    "tokenUri": "https://authorization.server/as/token.oauth2",
    "userInfoUri": "https://authorization.server/idp/userinfo.openid",
    "userNameAttribute": "sub",
    "jwkSetUri": "https://authorization.server/pf/JWKS",
    "introspectionUri": null
  }
}

...

Additional security considerations

General rules

  • Groups contained inside the group claim, will be added as GrantedAuthorities with the prefix GROUP_* .

  • Special ROLE_SYSTEM authority to system clients.

  • Admin members will get ROLE_ADMIN for an easier identification.

...

External Jupyter Notebook

Distinguishing between browser and non-browser requests

With OAuth2 enabled, when an unauthenticated user tries to access or perform an action against ModelOp Center using an external Jupyter notebook, they will not be allowed to do so until they authenticate. The trigger for the authentication logic, located in the jupyter-plugin repository, is a 401 Unauthorized status code. However, Spring Security configured as OAuth2Login is no longer sending a 401 Unauthorized, but instead a 302 Found status code. To override the 302 Found status code, we introduced the CustomAuthenticationEntryPoint class. The purpose of this class is to inspect all requests for protected resources coming from an unauthenticated user, and to determine if a 302 Found or 401 Unauthorized status code should be returned.
We identify external Jupyter notebook requests (non-browser requests) by checking for the Accept header and its value. If a request is coming from an external Jupyter notebook (non-browser request), then the Accept header will not contain the text/html value, in which case we return 401 Unauthorized. Otherwise, we return 302 Found and redirect to the login page.

To enable the use of CustomAuthenticationEntryPoint class, include the following line in the odg-gateway-service repository SecurityConfig class:

Code Block
http.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint(URI.create(this.authenticationFailureRedirectUri)));