Integration into a host application

The integration of the SKA Login Page can be done in two different ways. The first is to use this SKA Login Page project as reference and copy the needed code into your host application as local code. The second is to use Webpack5 remote modules exposed by this SKA Login Page project and import and integrate those into your host application. The latter option still need some refinement.

Prerequisites

Application registration

To integrate MS Entra authentication into a SPA (Single Page Application) or WEB API, the application needs to be registered with MS Entra by the IT administrators. This registration can be done through the IT Support Service Desk and opening a request application registration for SSO ticket.

For this registration you will need:

  • Your application name.

  • All the redirect URL’s that is expected for this application. This is the URL where your application will be hosted and it is used by MS Entra to redirect the user back to the application after authentication has been completed. If possible, include a local host and port that is used during development, as this allows the authentication to be completed on a local instance as well. An example of the redirect URL’s might look like:

http://localhost:8100/
https://sdhp.stfc.skao.int/dp-naledi/dashboard/
https://sdhp.stfc.skao.int/integration-ska-sdp-dataproduct-dashboard/dashboard/
https://k8s.stfc.skao.int/staging-ska-sdp-dataproduct-dashboard/dashboard/
https://sdhp.stfc.skao.int/ci-dev-ska-sdp-dataproduct-dashboard/dashboard/
  • Also note that there are two different app registration types, and the one required for your application need to be specified. The first is for front-end SPA (Single Page Applications), the other is for API services for example FastAPI, that requires a WEB API registration. Indicate that in the purpose of the SSO field on the IT support request, as the wrong type of registration will cause the authentication to fail.

  • You will be supplied the application registration details as a One Time Secret when the application has been registered. You can save these in the HashiCorp Vault

  • The two required keys are the client ID and tenant id, these can be saved for example as:

REACT_APP_MSENTRA_CLIENT_ID=...
REACT_APP_MSENTRA_TENANT_ID=...

Note that when working with React and using environment variables, its a convention to prefix your custom environment variables with REACT_APP_*.

Integration of the MS Entra Provider into the host

To enable MS Entra authentication in a SPA, you need to wrap your application in the auth provider. You can do that by installing the following dependencies:

yarn add @azure/msal-browser
yarn add @azure/msal-react

Then copy the auth context file “src/components/Auth/AuthContext.tsx” into your project and add the provider to you project as is done here: “src/index.jsx”

You also need to add the MS Entra authConfig to your project “src/authConfig.js”

Integration of the environment variables

Your application will need the following environment variables to be available. You can create them in your .env file as empty strings, and add them to the relevant env.ts and constants as required in your project. When deployed via helm, these two ID’s will be populated with values from the vault. When testing locally, a local .env file with the app keys can be used. A way to handle this more securely needs to be determined and caution should be taken not to commit these keys to the repository.

REACT_APP_MSENTRA_CLIENT_ID=''
REACT_APP_MSENTRA_TENANT_ID=''
REACT_APP_MSENTRA_REDIRECT_URI=''
REACT_APP_ALLOW_MOCK_AUTH='true'
REACT_APP_PERMISSIONS_API_URI='<Your URL where the Permission API is hosted>/v1/getuserrole'

Integration into the host chart

In your host application templates, you need to add the annotations for the use of the vault:

annotations:
{{ if ((.Values.ui.vault).useVault) }}
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/agent-inject-status: "update"
    vault.hashicorp.com/agent-inject-secret-config: "{{ .Values.ui.vault.pathToSecretVault }}"
    vault.hashicorp.com/agent-inject-template-config: |
        {{`{{- with secret `}}"{{ .Values.ui.vault.pathToSecretVault }}"{{` -}}`}}
        {{`{{- range $k, $v := .Data.data }}`}}
        {{`export {{ $k }}={{ $v }}`}}
        {{`{{- end }}`}}
        {{`{{- end }}`}}
    vault.hashicorp.com/role: "kube-role"
{{ end }}

As well as the environment variables:

env:
  - name: REACT_APP_MSENTRA_REDIRECT_URI
    value: "{{ .Values.ingress.hostname }}{{ include "ska-login-page.ui.ingress.path" . }}/"
  - name: REACT_APP_MSENTRA_CLIENT_ID
    value: "{{ .Values.ui.vault.client_id }}"
  - name: REACT_APP_MSENTRA_TENANT_ID
    value: "{{ .Values.ui.vault.tenant_id }}"
  - name: REACT_APP_ALLOW_MOCK_AUTH
    value: "{{ .Values.ui.config.allowMockAuth }}"
  - name: REACT_APP_PERMISSIONS_API_URI
    value: "{{ .Values.ingress.hostname }}{{ include "ska-login-page.permissionsApi.ingress.path" . }}/v1/getuserrole"

Lastly you need to add the source to your secrets that get injected by the vault into your pod. This can be done by adding the source into your nginx_env_config.sh in the case of a front-end application:

source /vault/secrets/config

Integration as local code in the host

To integrate the SKA Login components into your project as local code, copy the auth component from src/components/Auth into your project. From there you can use the MockAuthDialogs, SwitchAuthButton, SignInButton, SignOutButton and the LoadUserData function in your project. You can use the integration into this applications shell component as a reference.

Integration as a MF Remote module

NOTE: This option still needs some refinement.

The SKA-Login-Page has been configured to expose the the following modules with Webpack5:

exposes: {
  './MockAuthDialogs': './src/components/Auth/MockAuth/MockAuthDialogs/MockAuthDialogs.tsx',
  './SwitchAuthButton': './src/components/Auth/SwitchAuthButton.tsx',
  './SignInButton': './src/components/Auth/SignInButton.tsx',
  './SignOutButton': './src/components/Auth/SignOutButton.tsx'
},

This allows the components to be imported separately into a host application.

import {
  LoadMFRemoteComponent,
  DynamicLoader
} from '@services/dynamicLoader/dynamicLoader';
import { REMOTE_SKA_LOGIN_APP_URL } from '@utils/constants';

const NAME = 'skaLoginPage';

export const MockAuthDialogs = LoadMFRemoteComponent({
  scope: NAME,
  module: './MockAuthDialogs',
  url: REMOTE_SKA_LOGIN_APP_URL
});

export function SwitchAuthButton() {
  return DynamicLoader({
    scope: NAME,
    module: './SwitchAuthButton',
    url: REMOTE_SKA_LOGIN_APP_URL
  });
}

export function SignInButton() {
  return DynamicLoader({
    scope: NAME,
    module: './SignInButton',
    url: REMOTE_SKA_LOGIN_APP_URL
  });
}

export function SignOutButton() {
  return DynamicLoader({
    scope: NAME,
    module: './SignOutButton',
    url: REMOTE_SKA_LOGIN_APP_URL
  });
}

You can then use these 4 components as part of your application.