Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
PlantUML
border1
titleWeb UI SSO Flow (SAML)
hide footbox
autonumber
 
participant "Browser" as cli
participant "WebUI\n(eg NN UI)" as ui #lime
participant "Knox\nTS/SSO" as sso #lime
participant "SAML IdP\n(eg Shibboleth)" as idp
 
activate cli
cli -> ui: /view.GET()
  note right: User/browser makes request to UI without valid token
  activate ui
  cli <-- ui: redirect302(SSO:/login,ui-origin-url)
  note right: AuthFilter in UI detectes no/invalid token redirects to KnoxTS/SSO preserving ui-origin-url
  deactivate ui
cli -> sso: /login.GET(ui-origin-uil)
  note right: Browser follows redirect
  activate sso
  cli <-- sso: redirect302(IdP:/login,knox-origin-url)
  note right: KnoxTS/SSO finds no/invalid token,\nredirects to SAML IdP preserving knox-origin-url with encoded ui-origin-uri
  deactivate sso
cli -> idp: /login.GET(knox-origin-url)
  note right: Browser follows redirect
  activate idp
  cli <-- idp: ok200(form)
  note right: SAML IdP presents login form to user
  deactivate idp
cli -> idp: /login.POST(username,password)
note right: User provides credentials to IdP via login form.\nSAML IdP validates credentials.
  activate idp
  cli <-- idp: redirect302(knox-origin-url,saml-bearer-token)
  note right: IdP redirects back to knox-origin-url with SAML Bearer token in headers
  deactivate idp
cli -> sso: /login.GET(saml-bearer-token)
  note right: KnoxTS/SSO converts SAML Bearer Token to a normalized JWT Bearer Token\nand extracts ui-origin-url from knox-origin-url
  activate sso
  cli <-- sso: redirect302(ui-origin-url,jwt-bearer-token-cookie)
  note right: KnoxTS/SSO redirects client back to ui-origin-url with JWT Bearer token in cookie
  deactivate sso
cli -> ui: /view.GET(jwt-bearer-token-cookie)
note right: Browser follows redirect to ui-origin-url with JWT Bearer Token in cookie.\nJWT Bearer Token validated by AuthFilter in UI
  activate ui
  cli <- ui: ok200(response)
  note right: Request processes and response returned to client.
  deactivate ui
deactivate cli
 

Proof of Concept Status

The current POC effort is proving the above flow and trying to minimize the work required on the UI.

The following notes reflect the POC state for the above flow:

  1. On first request to a given UI with the redirecting authentication handler, the hadoop auth filter sees that there is no hadoop auth cookie and delegates to the configured handler. The redirecting authentication handler looks for a simple cookie that represents a knoxsso token (this may be changed to a JWT bearer token or cookie). In the absence of this cookie, the handler redirects the browser to the configured endpoint for knoxsso and passes the original UI url as a request parameter "originalUrl". Example: http://localhost:8888/knoxsso?originalUrl=http://localhost:8888/app/
  2. The knoxsso endpoint has a number of filters. The first captures the original url parameter and creates a cookie called original-url to be used later to redirect the user to the UI once authentication has been successfully accomplished. Example: original-url http://localhost:8888/app/
  3. The next filter is the JBoss picketlink SPFilter for SAML service providers. It redirects the user to the IdP (shibboleth running in a centos VM hosted in jetty) to challenge for credentials where the user is currently authenticated against the Knox demo ApacheDS LDAP server. This could be any LDAP server or AD. Once the user is successfully authenticated the IdP redirects the user back the knoxsso endpoint. The capture filter ignores the incoming POST since it doesn't have the originalUrl parameter and allows the processing to go back to the picketlink filter where the assertion is accepted and the userid extracted and made available to the servlet programming model through HttpServletRequest.getUserPrincipal.
  4. The next filter is for redirecting back to the UI with a token that can be consumed by the UI authentication handler. This redirecting filter extracts the userid from getUserPrincipal and creates a cookie that simply has the username as the value. Example: hadoop-auth guest It then extracts the original-url from the cookie that was added by the capture filter and redirects the users with token cookie to the original url. Example: original-url http://localhost:8888/app/
  5. The hadoop auth filter on the UI endpoint accepts the requests but still finds no hadoop auth cookie and delegates once again to the redirect authentication handler. The auth handler finds the expected cookie/token and extracts the userid, creates a hadoop authentication token and returns it to the filter. The filter creates a hadoop auth cookie for this token and uses this for authentication until it expires and is no longer presented by the browser and we start back at #1.

Additional Notes

  • Cookie domains may not need to be the same across all UIs using this approach
  • In order to do a more complicated/secure token between knoxsso and the UI - we will need to verify signature using a common key. This will likely require the use of the KeyProvider API or CredentialProvider API. This will also require either:
    • a central KMS provider that will allow contrained access to the same key materials by knoxsso and the UI auth handler
    • separate keystores that will need the key provisioned independently and to stay in sync
  • Normalizing on JWT as the token that is consumed by the UI auth handler will require some JWT parsing and verification code to be available in hadoop. Not sure if it can be put into hadoop auth module or whether it needs to go into common/security.
  • This same architecture can be used with other implementations on the knoxsso side in place of the SAML/Shibboleth integration. We will have to make this configurable. The first filter will also capture the original url and the last will always redirect back to the original url. The processing that goes on in between can be pluggable to accommodate various integrations with SSO providers, simple hosted mechanisms (FORM, HTTP Basic), etc.

 

PlantUML
border1
titleWeb UI SSO Flow (SAML)
hide footbox
autonumber

participant "Browser" as cli
participant "WebUI\n(eg NN UI)" as ui
participant "Knox\nTS/SSO" as sso
participant "SAML\nIdP" as idp
 
activate cli
cli -> ui: page.GET()
  activate ui
  cli <-- ui: redirect(IDP.login)
  deactivate ui
cli -> idp: login.GET()
  activate idp
  cli <-- idp: form
  deactivate idp
cli -> idp: form.POST(username,password)
  activate idp
  cli <-- idp: redirect(SSO.translate):saml-bearer-token
  deactivate idp
cli -> sso: translate.GET(saml-bearer-token)
  activate sso
  cli <-- sso: redirect(WebUI.page):jwt-bearer-token-cookie
  deactivate sso
cli -> ui: page.GET(jwt-bearer-token-cookie)
  activate ui
  cli <- ui: response
  deactivate ui
deactivate cli

...