diff --git a/libs/auth/react/.babelrc b/libs/auth/react/.babelrc
deleted file mode 100644
index e05c199e361e..000000000000
--- a/libs/auth/react/.babelrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "presets": ["@nx/react/babel"],
- "plugins": []
-}
diff --git a/libs/auth/react/.eslintrc.json b/libs/auth/react/.eslintrc.json
deleted file mode 100644
index 4f027ee445be..000000000000
--- a/libs/auth/react/.eslintrc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "extends": ["plugin:@nx/react", "../../../.eslintrc.json"],
- "ignorePatterns": ["!**/*"],
- "rules": {},
- "overrides": [
- { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": {} },
- { "files": ["*.ts", "*.tsx"], "rules": {} },
- { "files": ["*.js", "*.jsx"], "rules": {} }
- ]
-}
diff --git a/libs/auth/react/README.md b/libs/auth/react/README.md
deleted file mode 100644
index 039c3d156ae7..000000000000
--- a/libs/auth/react/README.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# @island.is/auth/react
-
-Manage authentication in React (non-next) single page applications.
-
-- Handles oidc-client and callback routes.
-- Handles authentication flow with loading screen.
-- Manages user context.
-- Renews access tokens on demand (when calling APIs) instead of continuously. This helps us support an (eg) 1-8 hour IDS session, depending on how long the user is active.
-- Preloads a new access token some time before it expires (when calling APIs).
-- Monitor the IDS session and restart login flow if the user is not logged in anymore.
-
-## Usage
-
-### Configure
-
-In the startup of your app (e.g. `Main.tsx`) you need to configure some authentication parameters:
-
-```typescript
-import { configure } from '@island.is/auth/react'
-import { environment } from './environments'
-
-configure({
- // You should usually configure these:
- authority: environment.identityServer.authority,
- client_id: '@island.is/web',
- scope: [
- 'openid',
- 'profile',
- 'api_resource.scope',
- '@island.is/applications:read',
- ],
- // These can be overridden to control callback urls.
- // These are the default values:
- baseUrl: `${window.location.origin}`,
- redirectPath: '/auth/callback',
- redirectPathSilent: '/auth/callback-silent',
-})
-```
-
-### Authenticate
-
-The configure function also accepts all oidc-client UserManager settings.
-
-Then you can render the Authenticator component around your application to wrap it with user authentication.
-
-```typescript jsx
-ReactDOM.render(
-
-
-
-
- ,
- document.getElementById('root'),
-)
-```
-
-By default, it only renders its children after signing the user in. It will render a loading screen in the meantime.
-
-{% hint style="info" %}
-Note: Authenticator must be rendered inside React Router to set up callback routes.
-{% endhint %}
-
-### Get access token
-
-You can configure authentication for your GraphQL client like this:
-
-```typescript
-import {
- ApolloClient,
- InMemoryCache,
- HttpLink,
- ApolloLink,
-} from '@apollo/client'
-import { authLink } from '@island.is/auth/react'
-
-const httpLink = new HttpLink(/* snip */)
-
-export const client = new ApolloClient({
- link: ApolloLink.from([authLink, httpLink]),
- cache: new InMemoryCache(),
-})
-```
-
-You can also manually get the access token like this:
-
-```typescript
-import { getAccessToken } from '@island.is/auth/react'
-
-const accessToken = await getAccessToken()
-```
-
-### Token renew and IDS session
-
-When you call `getAccessToken` or make requests with `authLink`, we renew the access token on demand if it has expired. We also preload a new access token if you are actively requesting the access token before it expires.
-
-Note that if the user has been inactive, they might experience a delay when they come back and call an API, while we renew the access token.
-
-Every time we renew the access token, the IDS session is extended. When this is written, the IDS maintains a 1 hour session that can be extended up to 8 hours.
-
-Be careful not to do continuous API requests on an interval when the user might not be active.
-
-Later we may implement an "updateActive" function that can be called to extend the IDS session in case the user is active but not calling any APIs.
-
-## Running unit tests
-
-Run `nx test auth-react` to execute the unit tests via [Jest](https://jestjs.io).
diff --git a/libs/auth/react/babel-jest.config.json b/libs/auth/react/babel-jest.config.json
deleted file mode 100644
index f83bce0d90ea..000000000000
--- a/libs/auth/react/babel-jest.config.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "presets": [
- [
- "@babel/preset-env",
- {
- "targets": {
- "node": "current"
- }
- }
- ],
- "@babel/preset-typescript",
- "@babel/preset-react"
- ],
- "plugins": ["@vanilla-extract/babel-plugin"]
-}
diff --git a/libs/auth/react/jest.config.ts b/libs/auth/react/jest.config.ts
deleted file mode 100644
index 336f7f818324..000000000000
--- a/libs/auth/react/jest.config.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-/* eslint-disable */
-export default {
- displayName: 'auth-react',
- preset: './jest.preset.js',
- rootDir: '../../..',
- roots: [__dirname],
- setupFilesAfterEnv: [`${__dirname}/test/setup.ts`],
- transform: {
- '^.+\\.[tj]sx?$': [
- 'babel-jest',
- { cwd: __dirname, configFile: `${__dirname}/babel-jest.config.json` },
- ],
- },
- moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
- coverageDirectory: '/coverage/libs/auth/react',
-}
diff --git a/libs/auth/react/project.json b/libs/auth/react/project.json
deleted file mode 100644
index 51a8e03a6a39..000000000000
--- a/libs/auth/react/project.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "auth-react",
- "$schema": "../../../node_modules/nx/schemas/project-schema.json",
- "sourceRoot": "libs/auth/react/src",
- "projectType": "library",
- "tags": ["lib:react-spa", "scope:react-spa"],
- "targets": {
- "lint": {
- "executor": "@nx/eslint:lint"
- },
- "test": {
- "executor": "@nx/jest:jest",
- "outputs": ["{workspaceRoot}/coverage/libs/auth/react"],
- "options": {
- "jestConfig": "libs/auth/react/jest.config.ts"
- }
- }
- }
-}
diff --git a/libs/auth/react/src/index.ts b/libs/auth/react/src/index.ts
deleted file mode 100644
index 99c01c660442..000000000000
--- a/libs/auth/react/src/index.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-// Components
-export * from './lib/auth/AuthProvider'
-export * from './lib/auth/MockedAuthProvider'
-export * from './lib/auth/AuthContext'
-
-// Lib
-export * from './lib/userManager'
-export * from './lib/authLink'
-export { getAccessToken } from './lib/getAccessToken'
-
-// Types
-export type { MockUser } from './lib/createMockUser'
-export type { AuthSettings } from './lib/AuthSettings'
-export * from './lib/createMockUser'
diff --git a/libs/auth/react/src/lib/AuthSettings.spec.ts b/libs/auth/react/src/lib/AuthSettings.spec.ts
deleted file mode 100644
index a2edf3423518..000000000000
--- a/libs/auth/react/src/lib/AuthSettings.spec.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { mergeAuthSettings } from './AuthSettings'
-
-describe('mergeAuthSettings', () => {
- it('provides good defaults', () => {
- // act
- const settings = mergeAuthSettings({
- client_id: 'test-client',
- authority: 'https://innskra.island.is',
- })
-
- // assert
- expect(settings).toMatchInlineSnapshot(`
- Object {
- "authority": "https://innskra.island.is",
- "automaticSilentRenew": false,
- "baseUrl": "http://localhost",
- "checkSessionPath": "/connect/sessioninfo",
- "client_id": "test-client",
- "loadUserInfo": true,
- "mergeClaims": true,
- "monitorSession": false,
- "post_logout_redirect_uri": "http://localhost",
- "redirectPath": "/auth/callback",
- "redirectPathSilent": "/auth/callback-silent",
- "response_type": "code",
- "revokeTokenTypes": Array [
- "refresh_token",
- ],
- "revokeTokensOnSignout": true,
- "silent_redirect_uri": "http://localhost/auth/callback-silent",
- "userStore": WebStorageStateStore {
- "_logger": Logger {
- "_name": "WebStorageStateStore",
- },
- "_prefix": "oidc.",
- "_store": Storage {},
- },
- }
- `)
- })
-
- it('creates uris from baseUrl and redirect paths', () => {
- // act
- const settings = mergeAuthSettings({
- authority: 'https://innskra.island.is',
- client_id: 'test-client',
- baseUrl: 'https://island.is',
- redirectPath: '/auth',
- redirectPathSilent: '/auth-silent',
- })
-
- // assert
- expect(settings).toMatchObject({
- baseUrl: 'https://island.is',
- post_logout_redirect_uri: 'https://island.is',
- redirectPath: '/auth',
- redirectPathSilent: '/auth-silent',
- silent_redirect_uri: 'https://island.is/auth-silent',
- })
- })
-})
diff --git a/libs/auth/react/src/lib/AuthSettings.ts b/libs/auth/react/src/lib/AuthSettings.ts
deleted file mode 100644
index c35c7ee8c65a..000000000000
--- a/libs/auth/react/src/lib/AuthSettings.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { storageFactory } from '@island.is/shared/utils'
-import { UserManagerSettings, WebStorageStateStore } from 'oidc-client-ts'
-
-export interface AuthSettings
- extends Omit {
- /*
- * Used to create redirect uris. Should not end with slash.
- * Default: window.location.origin
- */
- baseUrl?: string
-
- /*
- * Used to handle login callback and to build a default value for `redirect_uri` with baseUrl. Should be
- * relative from baseUrl and start with a "/".
- * Default: "/auth/callback"
- */
- redirectPath?: string
-
- /**
- * Used to handle login callback and to build a default value for `silent_redirect_uri` with baseUrl.
- * Should be relative from baseUrl and start with a "/".
- * Default: "/auth/callback-silent"
- */
- redirectPathSilent?: string
-
- /**
- * Used to support login flow triggered by the authorisation server or another party. Should be relative from baseUrl
- * and start with a "/".
- * More information: https://openid.net/specs/openid-connect-standard-1_0-21.html#client_Initiate_login
- * Default: undefined
- */
- initiateLoginPath?: string
-
- /**
- * Prefix for storing user access tokens in session storage.
- */
- userStorePrefix?: string
-
- /**
- * Allow to pass the scope as an array.
- */
- scope?: string[]
-
- /**
- * Which URL to send the user to after switching users.
- */
- switchUserRedirectUrl?: string
-
- /**
- * Which PATH on the AUTHORITY to use for checking the session expiry.
- */
- checkSessionPath?: string
-}
-
-export const mergeAuthSettings = (settings: AuthSettings): AuthSettings => {
- const baseUrl = settings.baseUrl ?? window.location.origin
- const redirectPath = settings.redirectPath ?? '/auth/callback'
- const redirectPathSilent =
- settings.redirectPathSilent ?? '/auth/callback-silent'
-
- // Many Open ID Connect features only work when on the same domain as the IDS (with first party cookies)
- const onIdsDomain = /(is|dev)land.is$/.test(window.location.origin)
-
- return {
- baseUrl,
- redirectPath,
- redirectPathSilent,
- automaticSilentRenew: false,
- checkSessionPath: '/connect/sessioninfo',
- silent_redirect_uri: `${baseUrl}${redirectPathSilent}`,
- post_logout_redirect_uri: baseUrl,
- response_type: 'code',
- revokeTokenTypes: ['refresh_token'],
- revokeTokensOnSignout: true,
- loadUserInfo: true,
- monitorSession: onIdsDomain,
- userStore: new WebStorageStateStore({
- store: storageFactory(() => sessionStorage),
- prefix: settings.userStorePrefix,
- }),
- mergeClaims: true,
- ...settings,
- }
-}
diff --git a/libs/auth/react/src/lib/auth/Auth.css.ts b/libs/auth/react/src/lib/auth/Auth.css.ts
deleted file mode 100644
index 62d600b0be1b..000000000000
--- a/libs/auth/react/src/lib/auth/Auth.css.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { style } from '@vanilla-extract/css'
-
-export const fullScreen = style({
- height: '100vh',
-})
diff --git a/libs/auth/react/src/lib/auth/Auth.state.ts b/libs/auth/react/src/lib/auth/Auth.state.ts
deleted file mode 100644
index 74a1b1f9b785..000000000000
--- a/libs/auth/react/src/lib/auth/Auth.state.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import { User } from '@island.is/shared/types'
-
-export type AuthState =
- | 'logged-out'
- | 'loading'
- | 'logged-in'
- | 'failed'
- | 'switching'
- | 'logging-out'
-
-export interface AuthReducerState {
- userInfo: User | null
- authState: AuthState
- isAuthenticated: boolean
-}
-
-export enum ActionType {
- SIGNIN_START = 'SIGNIN_START',
- SIGNIN_SUCCESS = 'SIGNIN_SUCCESS',
- SIGNIN_FAILURE = 'SIGNIN_FAILURE',
- LOGGING_OUT = 'LOGGING_OUT',
- LOGGED_OUT = 'LOGGED_OUT',
- USER_LOADED = 'USER_LOADED',
- SWITCH_USER = 'SWITCH_USER',
-}
-
-export interface Action {
- type: ActionType
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- payload?: any
-}
-
-export const initialState: AuthReducerState = {
- userInfo: null,
- authState: 'logged-out',
- isAuthenticated: false,
-}
-
-export const reducer = (
- state: AuthReducerState,
- action: Action,
-): AuthReducerState => {
- switch (action.type) {
- case ActionType.SIGNIN_START:
- return {
- ...state,
- authState: 'loading',
- }
- case ActionType.SIGNIN_SUCCESS:
- return {
- ...state,
- userInfo: action.payload,
-
- authState: 'logged-in',
- isAuthenticated: true,
- }
- case ActionType.USER_LOADED:
- return state.isAuthenticated
- ? {
- ...state,
- userInfo: action.payload,
- }
- : state
- case ActionType.SIGNIN_FAILURE:
- return {
- ...state,
- authState: 'failed',
- }
- case ActionType.LOGGING_OUT:
- return {
- ...state,
- authState: 'logging-out',
- }
- case ActionType.SWITCH_USER:
- return {
- ...state,
- authState: 'switching',
- }
- case ActionType.LOGGED_OUT:
- return {
- ...initialState,
- }
- default:
- return state
- }
-}
diff --git a/libs/auth/react/src/lib/auth/AuthContext.tsx b/libs/auth/react/src/lib/auth/AuthContext.tsx
deleted file mode 100644
index e6d65ea5d94a..000000000000
--- a/libs/auth/react/src/lib/auth/AuthContext.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createContext, useContext } from 'react'
-
-import { AuthReducerState, initialState } from './Auth.state'
-
-export interface AuthContextType extends AuthReducerState {
- signIn(): void
- signInSilent(): void
- switchUser(nationalId?: string): void
- signOut(): void
- authority?: string
-}
-
-export const defaultAuthContext = {
- ...initialState,
- signIn() {
- // Intentionally empty
- },
- signInSilent() {
- // Intentionally empty
- },
- switchUser(_nationalId?: string) {
- // Intentionally empty
- },
- signOut() {
- // Intentionally empty
- },
-}
-
-export const AuthContext = createContext(defaultAuthContext)
-
-const warnDeprecated = (hookName: string, alternative: string) => {
- console.warn(
- `[Deprecation Warning] "${hookName}" is being replaced by BFF auth pattern Please use "${alternative}" from "libs/react-spa/bff".`,
- )
-}
-
-/**
- * @deprecated Use useBff from `libs/react-spa/bff` instead.
- */
-export const useAuth = () => {
- warnDeprecated('useAuth', 'useBff')
-
- const context = useContext(AuthContext)
-
- if (!context) {
- throw new Error('useAuth must be used within a AuthProvider')
- }
-
- return context
-}
-
-/**
- * @deprecated Use useUserInfo from `libs/react-spa/bff` instead.
- */
-export const useUserInfo = () => {
- warnDeprecated('useUserInfo', 'useUserInfo')
- const { userInfo } = useAuth()
-
- if (!userInfo) {
- throw new Error('User info is not available. Is the user authenticated?')
- }
-
- return userInfo
-}
diff --git a/libs/auth/react/src/lib/auth/AuthErrorScreen.tsx b/libs/auth/react/src/lib/auth/AuthErrorScreen.tsx
deleted file mode 100644
index 27bcfe5aeb03..000000000000
--- a/libs/auth/react/src/lib/auth/AuthErrorScreen.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react'
-import { Box, Button, ProblemTemplate } from '@island.is/island-ui/core'
-
-import * as styles from './Auth.css'
-
-type AuthenticatorErrorScreenProps = {
- /**
- * Retry callback
- */
- onRetry(): void
-}
-
-// This screen is unfortunately not translated because at this point we don't
-// have a user locale, nor an access token to fetch translations.
-export const AuthErrorScreen = ({ onRetry }: AuthenticatorErrorScreenProps) => (
-
-
- Vinsamlegast reyndu aftur síðar.{' '}
-
- >
- }
- />
-
-)
diff --git a/libs/auth/react/src/lib/auth/AuthProvider.mocked.spec.tsx b/libs/auth/react/src/lib/auth/AuthProvider.mocked.spec.tsx
deleted file mode 100644
index 3cc638999238..000000000000
--- a/libs/auth/react/src/lib/auth/AuthProvider.mocked.spec.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { FC } from 'react'
-import { render, screen } from '@testing-library/react'
-import { MemoryRouter } from 'react-router-dom'
-
-import { configureMock } from '../userManager'
-import { useAuth } from './AuthContext'
-import { AuthProvider } from './AuthProvider'
-
-const Wrapper: FC> = ({ children }) => (
- {children}
-)
-const Greeting = () => {
- const { userInfo } = useAuth()
- return <>Hello {userInfo?.profile.name}>
-}
-const renderAuthenticator = () =>
- render(
-
-
-
-
- ,
- { wrapper: Wrapper },
- )
-
-describe('AuthProvider', () => {
- const expectAuthenticated = (name: string) =>
- screen.findByText(`Hello ${name}`)
-
- it('authenticates with non-expired user', async () => {
- // Arrange
- configureMock({
- profile: {
- name: 'John Doe',
- },
- })
-
- // Act
- renderAuthenticator()
-
- // Assert
- await expectAuthenticated('John Doe')
- })
-})
diff --git a/libs/auth/react/src/lib/auth/AuthProvider.spec.tsx b/libs/auth/react/src/lib/auth/AuthProvider.spec.tsx
deleted file mode 100644
index ab1d4a03049f..000000000000
--- a/libs/auth/react/src/lib/auth/AuthProvider.spec.tsx
+++ /dev/null
@@ -1,241 +0,0 @@
-import { act, render, screen, waitFor } from '@testing-library/react'
-import { UserManagerEvents } from 'oidc-client-ts'
-import { BrowserRouter } from 'react-router-dom'
-
-import { getAuthSettings, getUserManager } from '../userManager'
-import { useAuth } from './AuthContext'
-import { AuthProvider } from './AuthProvider'
-import { createNationalId } from '@island.is/testing/fixtures'
-
-const BASE_PATH = '/basepath'
-const INITIATE_LOGIN_PATH = '/login'
-
-jest.mock('../userManager')
-const mockedGetUserManager = getUserManager as jest.Mock
-const mockedGetAuthSettings = getAuthSettings as jest.Mock
-
-const Greeting = () => {
- const { userInfo } = useAuth()
- return <>Hello {userInfo?.profile.name}>
-}
-
-const renderAuthenticator = (route = BASE_PATH) => {
- window.history.pushState({}, 'Test page', route)
-
- return render(
-
-
-
-
- ,
- { wrapper: BrowserRouter },
- )
-}
-
-type MinimalUser = {
- expired?: boolean
- profile?: {
- name: string
- }
-}
-type MinimalUserManager = {
- events: {
- addUserLoaded: (cb: UserManagerEvents) => void
- addUserSignedOut: jest.Mock
- removeUserLoaded: () => void
- removeUserSignedOut: () => void
- }
- getUser: jest.Mock>
- signinRedirect: jest.Mock
- signinSilent: jest.Mock
- signinRedirectCallback: jest.Mock
- removeUser: jest.Mock
-}
-
-describe('AuthProvider', () => {
- let userManager: MinimalUserManager
-
- const expectSignin = () =>
- waitFor(() => {
- if (userManager.signinRedirect.mock.calls.length === 0) {
- throw new Error('... wait')
- }
- })
-
- const expectAuthenticated = (name: string) =>
- screen.findByText(`Hello ${name}`)
-
- beforeEach(() => {
- userManager = {
- events: {
- addUserLoaded: jest.fn(),
- addUserSignedOut: jest.fn(),
- removeUserLoaded: jest.fn(),
- removeUserSignedOut: jest.fn(),
- },
- getUser: jest.fn(),
- signinRedirect: jest.fn(),
- signinSilent: jest.fn(),
- signinRedirectCallback: jest.fn(),
- removeUser: jest.fn(),
- }
- mockedGetUserManager.mockReturnValue(userManager)
- mockedGetAuthSettings.mockReturnValue({
- baseUrl: BASE_PATH,
- initiateLoginPath: INITIATE_LOGIN_PATH,
- redirectPath: '/callback',
- redirectPathSilent: '/callback-silent',
- })
- })
-
- it('starts signin flow when no stored user', async () => {
- // Act
- renderAuthenticator()
-
- // Assert
- await expectSignin()
- })
-
- it('should show a progress bar while authenticating', async () => {
- // Act
- const { getByRole } = renderAuthenticator()
-
- // Assert
- getByRole('progressbar')
- await expectSignin()
- })
-
- it('authenticates with non-expired user', async () => {
- // Arrange
- userManager.getUser.mockResolvedValue({
- expired: false,
- profile: {
- name: 'John',
- },
- })
-
- // Act
- renderAuthenticator()
-
- // Assert
- await expectAuthenticated('John')
- })
-
- it('removes user and starts signin flow if user is logged out', async () => {
- // Arrange
- userManager.getUser.mockResolvedValue({
- expired: false,
- profile: {
- name: 'John',
- },
- })
- renderAuthenticator()
- await expectAuthenticated('John')
- expect(userManager.events.addUserSignedOut).toHaveBeenCalled()
- const handler = userManager.events.addUserSignedOut.mock.calls[0][0]
-
- // Act
- await act(async () => {
- await handler()
- })
-
- // Assert
- await expectSignin()
- expect(userManager.removeUser).toHaveBeenCalled()
- })
-
- it('performs silent signin with expired user', async () => {
- // Arrange
- userManager.getUser.mockResolvedValue({
- expired: true,
- })
- userManager.signinSilent.mockResolvedValue({
- profile: {
- name: 'Doe',
- },
- })
-
- // Act
- renderAuthenticator()
-
- // Assert
- await expectAuthenticated('Doe')
- expect(userManager.signinSilent).toHaveBeenCalled()
- })
-
- it('starts signin flow if silent signin fails', async () => {
- // Arrange
- userManager.getUser.mockResolvedValue({
- expired: true,
- })
- userManager.signinSilent.mockRejectedValue(new Error('Not signed in'))
-
- // Act
- renderAuthenticator()
-
- // Assert
- await expectSignin()
- expect(userManager.signinSilent).toHaveBeenCalled()
- })
-
- // prettier-ignore
- it.each`
- params
- ${{ prompt: 'login' }}
- ${{ prompt: 'select_account' }}
- ${{
- login_hint: createNationalId('company'),
- target_link_uri: `${BASE_PATH}/test`,
- }}
- `(
- 'starts 3rd party initiated login flow with params $params',
- async (params: { prompt?: string, login_hint?: string, target_link_uri?: string }) => {
- // Arrange
- const searchParams = new URLSearchParams(params)
-
- // Act
- renderAuthenticator(
- `${BASE_PATH}${INITIATE_LOGIN_PATH}?${searchParams.toString()}`,
- )
-
- // Assert
- await expectSignin()
- expect(userManager.signinRedirect).toHaveBeenCalledWith({
- state: params.target_link_uri?.slice(BASE_PATH.length) ?? '/',
- login_hint: params.login_hint,
- prompt: params.prompt,
- })
- },
- )
-
- it('shows error screen if signin has an error', async () => {
- // Arrange
- const testRoute = `${BASE_PATH}${mockedGetAuthSettings().redirectPath}`
- userManager.signinRedirectCallback.mockRejectedValue(
- new Error('Test error'),
- )
-
- // Act
- renderAuthenticator(testRoute)
-
- // Assert
- await screen.findByText('Innskráning mistókst')
- await screen.findByRole('button', { name: 'Reyna aftur' })
- })
-
- it('shows error screen if IDS is unavailable', async () => {
- // Arrange
- // When the OIDC client library fails to load the /.well-known/openid-configuration
- // the signinRedirect methods rejects the Promise with an Error.
- userManager.signinRedirect.mockRejectedValueOnce(
- new Error('Internal Server Error'),
- )
-
- // Act
- renderAuthenticator()
-
- // Assert
- await screen.findByText('Innskráning mistókst')
- await screen.findByRole('button', { name: 'Reyna aftur' })
- })
-})
diff --git a/libs/auth/react/src/lib/auth/AuthProvider.tsx b/libs/auth/react/src/lib/auth/AuthProvider.tsx
deleted file mode 100644
index 8243291478b5..000000000000
--- a/libs/auth/react/src/lib/auth/AuthProvider.tsx
+++ /dev/null
@@ -1,333 +0,0 @@
-import React, {
- useCallback,
- useEffect,
- useMemo,
- useReducer,
- ReactNode,
- useState,
-} from 'react'
-import type { SigninRedirectArgs, User } from 'oidc-client-ts'
-
-import { useEffectOnce } from '@island.is/react-spa/shared'
-import { isDefined } from '@island.is/shared/utils'
-import { LoadingScreen } from '@island.is/react/components'
-
-import { getAuthSettings, getUserManager } from '../userManager'
-import { ActionType, initialState, reducer } from './Auth.state'
-import { AuthSettings } from '../AuthSettings'
-import { AuthContext } from './AuthContext'
-import { AuthErrorScreen } from './AuthErrorScreen'
-import { CheckIdpSession } from './CheckIdpSession'
-
-interface AuthProviderProps {
- /**
- * If true, Authenticator automatically starts login flow and does not render children until user is fully logged in.
- * If false, children are responsible for rendering a login button and loading indicator.
- * Default: true
- */
- autoLogin?: boolean
- /**
- * The base path of the application.
- */
- basePath: string
- children: ReactNode
-}
-
-type GetReturnUrl = {
- returnUrl: string
-} & Pick
-
-const isCurrentRoute = (url: string, path?: string) =>
- isDefined(path) && url.startsWith(path)
-
-const getReturnUrl = ({ redirectPath, returnUrl }: GetReturnUrl) => {
- if (redirectPath && returnUrl.startsWith(redirectPath)) {
- return '/'
- }
-
- return returnUrl
-}
-
-const getCurrentUrl = (basePath: string) => {
- const url = `${window.location.pathname}${window.location.search}${window.location.hash}`
-
- if (url.startsWith(basePath)) {
- return url.slice(basePath.length)
- }
-
- return '/'
-}
-
-export const AuthProvider = ({
- children,
- autoLogin = true,
- basePath,
-}: AuthProviderProps) => {
- const [state, dispatch] = useReducer(reducer, initialState)
- const [error, setError] = useState()
- const userManager = getUserManager()
- const authSettings = getAuthSettings()
- const monitorUserSession = !authSettings.scope?.includes('offline_access')
-
- const signinRedirect = useCallback(
- async (args: SigninRedirectArgs) => {
- try {
- await userManager.signinRedirect(args)
- // On success Nothing more happens here since browser will redirect to IDS.
- } catch (error) {
- // On error we set the error state to show the error screen which provides the users with a retry button.
- console.error(error)
- setError(error)
- }
- },
- [userManager, setError],
- )
-
- const signIn = useCallback(
- async function signIn() {
- dispatch({
- type: ActionType.SIGNIN_START,
- })
-
- return signinRedirect({
- state: getReturnUrl({
- returnUrl: getCurrentUrl(basePath),
- redirectPath: authSettings.redirectPath,
- }),
- })
- },
- [dispatch, authSettings, basePath],
- )
-
- const signInSilent = useCallback(
- async function signInSilent() {
- let user = null
- dispatch({
- type: ActionType.SIGNIN_START,
- })
- try {
- user = await userManager.signinSilent()
- dispatch({ type: ActionType.SIGNIN_SUCCESS, payload: user })
- } catch (error) {
- console.error('AuthProvider: Silent signin failed', error)
- dispatch({ type: ActionType.SIGNIN_FAILURE })
- }
-
- return user
- },
- [userManager, dispatch],
- )
-
- const switchUser = useCallback(
- async function switchUser(nationalId?: string) {
- const args =
- nationalId !== undefined
- ? {
- login_hint: nationalId,
- /**
- * TODO: remove this.
- * It is currently required to switch delegations, but we'd like
- * the IDS to handle login_required and other potential road
- * blocks. Now OidcSignIn is handling login_required.
- */
- prompt: 'none',
- }
- : {
- prompt: 'select_account',
- }
-
- dispatch({
- type: ActionType.SWITCH_USER,
- })
-
- return signinRedirect({
- state:
- authSettings.switchUserRedirectUrl ??
- getReturnUrl({
- returnUrl: getCurrentUrl(basePath),
- redirectPath: authSettings.redirectPath,
- }),
- ...args,
- })
- // Nothing more happens here since browser will redirect to IDS.
- },
- [userManager, dispatch, authSettings, basePath],
- )
-
- const signOut = useCallback(
- async function signOut() {
- dispatch({
- type: ActionType.LOGGING_OUT,
- })
- await userManager.signoutRedirect()
- },
- [userManager, dispatch],
- )
-
- const checkLogin = useCallback(
- async function checkLogin() {
- dispatch({
- type: ActionType.SIGNIN_START,
- })
- const storedUser = await userManager.getUser()
-
- // Check expiry.
- if (storedUser && !storedUser.expired) {
- dispatch({
- type: ActionType.SIGNIN_SUCCESS,
- payload: storedUser,
- })
- } else if (autoLogin) {
- // If we find a user in SessionStorage, there's a fine chance that
- // it's just an expired token, and we can silently log in.
- if (storedUser && (await signInSilent())) {
- return
- }
-
- // If all else fails, redirect to the login page.
- await signIn()
- } else {
- // When not performing autologin, silently check if there's an IDP session.
- await signInSilent()
- }
- },
- [userManager, dispatch, signIn, signInSilent, autoLogin],
- )
-
- const hasUserInfo = state.userInfo !== null
- useEffect(() => {
- // Only add events when we have userInfo, to avoid race conditions with
- // oidc hooks.
- if (!hasUserInfo) {
- return
- }
-
- // This is raised when a new user state has been loaded with a silent login.
- const userLoaded = (user: User) => {
- dispatch({
- type: ActionType.USER_LOADED,
- payload: user,
- })
- }
-
- // This is raised when the user is signed out of the IDP.
- const userSignedOut = async () => {
- dispatch({
- type: ActionType.LOGGED_OUT,
- })
- await userManager.removeUser()
-
- if (autoLogin) {
- signIn()
- }
- }
-
- userManager.events.addUserLoaded(userLoaded)
- userManager.events.addUserSignedOut(userSignedOut)
- return () => {
- userManager.events.removeUserLoaded(userLoaded)
- userManager.events.removeUserSignedOut(userSignedOut)
- }
- }, [dispatch, userManager, signIn, autoLogin, hasUserInfo])
-
- const init = async () => {
- const currentUrl = getCurrentUrl(basePath)
-
- if (isCurrentRoute(currentUrl, authSettings.redirectPath)) {
- try {
- const user = await userManager.signinRedirectCallback(
- window.location.href,
- )
-
- const url = typeof user.state === 'string' ? user.state : '/'
- window.history.replaceState(null, '', basePath + url)
-
- dispatch({
- type: ActionType.SIGNIN_SUCCESS,
- payload: user,
- })
- } catch (e) {
- if (e.error === 'login_required') {
- // If trying to switch delegations and the IDS session is expired, we'll
- // see this error. So we'll try a proper signin.
- return signinRedirect({ state: e.state })
- }
- console.error('Error in oidc callback', e)
- setError(e)
- }
- } else if (isCurrentRoute(currentUrl, authSettings.redirectPathSilent)) {
- const userManager = getUserManager()
- userManager.signinSilentCallback().catch((e) => {
- console.log(e)
- setError(e)
- })
- } else if (isCurrentRoute(currentUrl, authSettings.initiateLoginPath)) {
- const userManager = getUserManager()
- const searchParams = new URL(window.location.href).searchParams
-
- const loginHint = searchParams.get('login_hint')
- const targetLinkUri = searchParams.get('target_link_uri')
- const path =
- targetLinkUri &&
- authSettings.baseUrl &&
- targetLinkUri.startsWith(authSettings.baseUrl)
- ? targetLinkUri.slice(authSettings.baseUrl.length)
- : '/'
- let prompt = searchParams.get('prompt')
- prompt =
- prompt && ['login', 'select_account'].includes(prompt) ? prompt : null
-
- const args = {
- state: path,
- prompt: prompt ?? undefined,
- login_hint: loginHint ?? undefined,
- }
- return signinRedirect(args)
- } else {
- checkLogin()
- }
- }
-
- useEffectOnce(() => {
- init()
- })
-
- const context = useMemo(
- () => ({
- ...state,
- signIn,
- signInSilent,
- switchUser,
- signOut,
- authority: authSettings.authority,
- }),
- [state, signIn, signInSilent, switchUser, signOut, authSettings.authority],
- )
-
- const url = getCurrentUrl(basePath)
- const isLoading =
- !state.userInfo ||
- // We need to display loading screen if current route is the redirectPath or redirectPathSilent.
- // This is because these paths are not part of our React Router routes.
- isCurrentRoute(url, authSettings?.redirectPath) ||
- isCurrentRoute(url, authSettings?.redirectPathSilent)
-
- const onRetry = () => {
- window.location.href = basePath
- }
-
- return (
-
- {error ? (
-
- ) : isLoading ? (
-
- ) : (
- <>
- {monitorUserSession && }
- {children}
- >
- )}
-
- )
-}
diff --git a/libs/auth/react/src/lib/auth/CheckIdpSession.tsx b/libs/auth/react/src/lib/auth/CheckIdpSession.tsx
deleted file mode 100644
index 1890dbd1efd6..000000000000
--- a/libs/auth/react/src/lib/auth/CheckIdpSession.tsx
+++ /dev/null
@@ -1,189 +0,0 @@
-import addSeconds from 'date-fns/addSeconds'
-import { useCallback, useEffect, useReducer, useRef } from 'react'
-import { getAuthSettings, getUserManager } from '../userManager'
-
-const UserSessionMessageType = 'SessionInfo'
-
-interface UserSessionMessage {
- // Type to use to filter postMessage messages
- type: typeof UserSessionMessageType
-
- // Status of the message received from IDP.
- status: 'Ok' | 'No Session' | 'Failure'
-
- // The time when the authenticated session expires.
- expiresUtc?: string
-
- // Number of seconds until the session expires.
- expiresIn?: number
-
- // Boolean flag to indicated if the Expires time is passed.
- isExpired?: boolean
-}
-
-interface UserSessionState {
- /* The expected time when the user session is ending. */
- sessionEnd: Date | null
-
- /**
- * An interval function that checks if the expected sessionEnd has passed.
- * When set this indicates that the user has an active session.
- */
- intervalHandle: ReturnType | null
-
- /* The number of times we have tried to load the iframe to receive a new session info message. */
- retryCount: number
-}
-
-const MAX_RETRIES = 2
-const ACTIVE_SESSION_DELAY = 5 * 1000
-const CHECK_SESSION_INTERVAL = 2 * 1000
-
-const EMPTY_SESSION: UserSessionState = {
- retryCount: 0,
- sessionEnd: null,
- intervalHandle: null,
-}
-
-/**
- * This component monitors if the user session is active on the Identity Provider (IDP).
- * When it detects that the user session is expired it redirects to the sign-in page on the IDP.
- *
- * It loads a script from the IDP's 'connect/sessioninfo' endpoint into an iframe.
- * The script uses the postMessage API to post UserSessionMessage, which contains
- * details if the session is expired or after how many seconds it will expire.
- * We use these details to register an interval to monitor the session expiration.
- */
-export const CheckIdpSession = () => {
- const userManager = getUserManager()
- const authSettings = getAuthSettings()
- const iframeSrc = `${authSettings.authority}${authSettings.checkSessionPath}`
- const [iframeId, reloadIframe] = useReducer((id) => id + 1, 0)
- const userSession = useRef({ ...EMPTY_SESSION })
-
- const isActive = useCallback(() => {
- // When intervalHandle is set it means we have registered
- // a setInterval to monitor an active user session.
- return !!userSession.current.intervalHandle
- }, [])
-
- const hasBeenActive = useCallback(() => {
- // When sessionEnd is set it means the has been active
- // as we have an earlier UserSessionMessage.
- return !!userSession.current.sessionEnd
- }, [])
-
- const resetUserSession = useCallback(() => {
- if (userSession.current.intervalHandle) {
- clearInterval(userSession.current.intervalHandle)
- }
- userSession.current.intervalHandle = null
- userSession.current.retryCount = 0
- // Intentionally not resetting sessionEnd as it
- // indicates that the user has had session before.
- }, [])
-
- const signInRedirect = useCallback(async () => {
- await userManager.removeUser()
- return window.location.reload()
- }, [userManager])
-
- const checkActiveSession = useCallback(() => {
- setTimeout(() => {
- const { retryCount } = userSession.current
-
- if (!isActive() && retryCount > MAX_RETRIES && hasBeenActive()) {
- // We were unable to retrieve a message from the IDP after max retries and have a reason
- // to believe that the session is expired (an earlier UserSessionMessage has expired).
- // So we reload the window just to be safe. This causes one of three things to happen:
- // - If the iframe is broken and the user does have a valid IDP session, they'll generally reload where they were.
- // - If the iframe is broken and the user does not have a valid IDP session, they're sent to the login page.
- // - If the user has a network problem, then they'll see a browser error screen, but at least any sensitive information is not visible any more.
- window.location.reload()
- } else if (!isActive() && retryCount < MAX_RETRIES) {
- userSession.current.retryCount += 1
- // We are unable to retrieve a message from the IDP,
- // so we reload the iframe to retry without reloading the window.
- reloadIframe()
- }
- }, ACTIVE_SESSION_DELAY)
- }, [isActive, hasBeenActive])
-
- const messageHandler = useCallback(
- async ({ data, origin }: MessageEvent): Promise => {
- const sessionInfo = data as UserSessionMessage
-
- // Check if the postMessage is meant for us
- if (
- origin !== authSettings.authority ||
- sessionInfo.type !== UserSessionMessageType
- ) {
- return
- }
-
- if (sessionInfo && sessionInfo.status === 'Ok') {
- // SessionInfo was found, check if it is valid or expired
- if (sessionInfo.isExpired) {
- return signInRedirect()
- } else if (!isActive() && sessionInfo.expiresIn !== undefined) {
- userSession.current.sessionEnd = addSeconds(
- new Date(),
- sessionInfo.expiresIn,
- )
-
- userSession.current.intervalHandle = setInterval(() => {
- const now = new Date()
-
- if (
- userSession.current.sessionEnd &&
- now > userSession.current.sessionEnd
- ) {
- // The expected session end has passed but the user might have extended their session.
- // So we reset the session state and reload the iframe to query new session info from the IDP.
- resetUserSession()
- reloadIframe()
- }
- }, CHECK_SESSION_INTERVAL)
- }
- } else if (
- sessionInfo &&
- sessionInfo.status === 'No Session' &&
- hasBeenActive()
- ) {
- return signInRedirect()
- }
-
- // Silent failure as we have failed to get sessionInfo but the user still might have valid session.
- // So we only trigger the signInRedirect flow when we get definite response about expired session.
- },
- [
- authSettings.authority,
- signInRedirect,
- isActive,
- hasBeenActive,
- resetUserSession,
- ],
- )
-
- useEffect(() => {
- window.addEventListener('message', messageHandler)
-
- return () => {
- window.removeEventListener('message', messageHandler)
- }
- }, [messageHandler])
-
- return (
-
- )
-}
diff --git a/libs/auth/react/src/lib/auth/MockedAuthProvider.spec.tsx b/libs/auth/react/src/lib/auth/MockedAuthProvider.spec.tsx
deleted file mode 100644
index c90e77a95cb0..000000000000
--- a/libs/auth/react/src/lib/auth/MockedAuthProvider.spec.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react'
-import { render } from '@testing-library/react'
-import '@testing-library/jest-dom'
-import { useAuth } from './AuthContext'
-import { MockedAuthProvider } from './MockedAuthProvider'
-
-const TestConsumer = () => {
- const { userInfo } = useAuth()
- return User: {userInfo ? userInfo.profile.name : 'Not logged in'}
-}
-
-describe('MockedAuthProvider', () => {
- it('defaults to unauthenticated', () => {
- const { getByText } = render(
-
-
- ,
- )
- expect(getByText(/^User:/)).toHaveTextContent('User: Not logged in')
- })
-
- it('provides good default values for user', () => {
- const { getByText } = render(
-
-
- ,
- )
- expect(getByText(/^User:/)).toHaveTextContent('User: Mock')
- })
-
- it('supports overriding user details', () => {
- const { getByText } = render(
-
-
- ,
- )
- expect(getByText(/^User:/)).toHaveTextContent('User: Peter')
- })
-})
diff --git a/libs/auth/react/src/lib/auth/MockedAuthProvider.tsx b/libs/auth/react/src/lib/auth/MockedAuthProvider.tsx
deleted file mode 100644
index 4da0e2de69e7..000000000000
--- a/libs/auth/react/src/lib/auth/MockedAuthProvider.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import React, { FC } from 'react'
-import { AuthContext, defaultAuthContext } from './AuthContext'
-import { createMockUser, MockUser } from '../createMockUser'
-
-interface MockedAuthenticatorProps {
- user?: MockUser
- signOut?: () => void
- switchUser?: (nationalId?: string) => void
-}
-
-export const MockedAuthProvider: FC<
- React.PropsWithChildren
-> = ({ children, signOut, switchUser, user }) => {
- const userInfo = user ? createMockUser(user) : null
- return (
-
- {children}
-
- )
-}
diff --git a/libs/auth/react/src/lib/authLink.ts b/libs/auth/react/src/lib/authLink.ts
deleted file mode 100644
index c097a99ec488..000000000000
--- a/libs/auth/react/src/lib/authLink.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { setContext } from '@apollo/client/link/context'
-import { getAccessToken } from './getAccessToken'
-
-export const authLink = setContext(async (_, { headers }) => {
- const token = await getAccessToken()
- return {
- headers: {
- ...headers,
- authorization: token ? `Bearer ${token}` : '',
- },
- }
-})
diff --git a/libs/auth/react/src/lib/createMockUser.ts b/libs/auth/react/src/lib/createMockUser.ts
deleted file mode 100644
index d7b7c87f62eb..000000000000
--- a/libs/auth/react/src/lib/createMockUser.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { User } from '@island.is/shared/types'
-
-export interface MockUser extends Partial> {
- profile?: Partial
-}
-
-export const createMockUser = (user?: MockUser) =>
- ({
- profile: {
- name: 'Mock',
- locale: 'is',
- nationalId: '0000000000',
- ...user?.profile,
- },
- expired: false,
- expires_in: 9999,
- scopes: [],
- ...user,
- } as User)
diff --git a/libs/auth/react/src/lib/getAccessToken.spec.ts b/libs/auth/react/src/lib/getAccessToken.spec.ts
deleted file mode 100644
index 56a67f0d76e2..000000000000
--- a/libs/auth/react/src/lib/getAccessToken.spec.ts
+++ /dev/null
@@ -1,152 +0,0 @@
-import {
- getAccessToken,
- MIN_EXPIRY_FOR_PRE_SIGNIN,
- MIN_EXPIRY_FOR_RE_SIGNIN,
-} from './getAccessToken'
-import { getUserManager } from './userManager'
-
-jest.mock('./userManager')
-const mockedGetUserManager = getUserManager as jest.Mock
-
-type MinimalUser = {
- access_token: string
- expires_in: number
-}
-
-type MinimalUserManager = {
- getUser: jest.Mock>
- signinSilent: jest.Mock>
-}
-
-describe('getAccessToken', () => {
- let userManager: MinimalUserManager
-
- beforeEach(() => {
- userManager = {
- getUser: jest.fn(),
- signinSilent: jest.fn(),
- }
- mockedGetUserManager.mockReturnValue(userManager)
- })
-
- it('gets access token from user', async () => {
- // Arrange
- const tokenValue = 'Test token'
- userManager.getUser.mockResolvedValue({
- access_token: tokenValue,
- expires_in: 1000,
- })
-
- // Act
- const token = await getAccessToken()
-
- // Assert
- expect(userManager.signinSilent).not.toHaveBeenCalled()
- expect(token).toBe(tokenValue)
- })
-
- it("returns null if there's no user", async () => {
- // Arrange
- userManager.getUser.mockResolvedValue(null)
-
- // Act
- const token = await getAccessToken()
-
- // Assert
- expect(token).toBe(null)
- })
-
- it("renews token if it's expired", async () => {
- // Arrange
- const tokenValue = 'Test token'
- userManager.getUser.mockResolvedValue({
- access_token: 'unused',
- expires_in: -100,
- })
- userManager.signinSilent.mockResolvedValue({
- access_token: tokenValue,
- expires_in: 1000,
- })
-
- // Act
- const token = await getAccessToken()
-
- // Assert
- expect(userManager.signinSilent).toHaveBeenCalled()
- expect(token).toBe(tokenValue)
- })
-
- it("renews token if it's almost expired", async () => {
- // Arrange
- const tokenValue = 'Test token'
- userManager.getUser.mockResolvedValue({
- access_token: 'unused',
- expires_in: MIN_EXPIRY_FOR_RE_SIGNIN - 1,
- })
- userManager.signinSilent.mockResolvedValue({
- access_token: tokenValue,
- expires_in: 1000,
- })
-
- // Act
- const token = await getAccessToken()
-
- // Assert
- expect(userManager.signinSilent).toHaveBeenCalled()
- expect(token).toBe(tokenValue)
- })
-
- it("returns null if there's no user when silently renewing", async () => {
- // Arrange
- userManager.getUser.mockResolvedValue({
- access_token: 'unused',
- expires_in: -100,
- })
- userManager.signinSilent.mockResolvedValue(null)
-
- // Act
- const token = await getAccessToken()
-
- // Assert
- expect(token).toBe(null)
- })
-
- it("prefetches token if it's about to expire but returns old token", async () => {
- // Arrange
- const tokenValue = 'Test token'
- userManager.getUser.mockResolvedValue({
- access_token: tokenValue,
- expires_in: MIN_EXPIRY_FOR_PRE_SIGNIN - 1,
- })
- userManager.signinSilent.mockResolvedValue(null)
-
- // Act
- const token = await getAccessToken()
-
- // Assert
- expect(userManager.signinSilent).toHaveBeenCalled()
- expect(token).toBe(tokenValue)
- })
-
- it('only silently renews once at a time', async () => {
- // Arrange
- const tokenValue = 'Test token'
- userManager.getUser.mockResolvedValue({
- access_token: 'unused',
- expires_in: -100,
- })
- userManager.signinSilent
- .mockResolvedValueOnce({ access_token: tokenValue, expires_in: 1000 })
- .mockResolvedValueOnce(null)
-
- // Act
- const promise1 = getAccessToken()
- const promise2 = getAccessToken()
- const [result1, result2] = await Promise.all([promise1, promise2])
-
- // Assert
- expect(userManager.signinSilent).toHaveBeenCalledTimes(1)
- expect(result1).toBe(tokenValue)
- expect(result2).toBe(tokenValue)
- })
-})
diff --git a/libs/auth/react/src/lib/getAccessToken.ts b/libs/auth/react/src/lib/getAccessToken.ts
deleted file mode 100644
index 6a5e15e8d7ff..000000000000
--- a/libs/auth/react/src/lib/getAccessToken.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { getUserManager } from './userManager'
-import { tinyMemoize } from './utils/tinyMemoize'
-
-// Should not use access tokens that are expired or just about to expire.
-// Get a new one just in case.
-export const MIN_EXPIRY_FOR_RE_SIGNIN = 10
-
-// If we call an API a couple of minutes before an access token, we assume
-// the user is still around and actively using the client. Then we prefetch a
-// new access token before it expires, to avoid request delays.
-export const MIN_EXPIRY_FOR_PRE_SIGNIN = 120
-
-const fetchNewToken = tinyMemoize(() => {
- // This can fail if IDP session is finished. This is ignored here and dealt
- // with in Authenticator.
- return getUserManager()
- .signinSilent()
- .catch(() => null)
-})
-
-export const getAccessToken = async () => {
- let user = await getUserManager().getUser()
- if (!user) {
- return null
- }
-
- // Token is either expired, or just about to expire. We should get a new
- // token either way.
- if (!user.expires_in || user.expires_in < MIN_EXPIRY_FOR_RE_SIGNIN) {
- user = await fetchNewToken()
- if (!user) {
- return null
- }
- }
-
- // We're still active but the token will expire soon. We'll make sure to
- // prefetch a new token for later.
- else if (!user.expires_in || user.expires_in < MIN_EXPIRY_FOR_PRE_SIGNIN) {
- // Intentionally not awaited. We don't want to delay the current request.
- fetchNewToken()
- }
-
- return user.access_token
-}
diff --git a/libs/auth/react/src/lib/userManager.ts b/libs/auth/react/src/lib/userManager.ts
deleted file mode 100644
index 1c685778018d..000000000000
--- a/libs/auth/react/src/lib/userManager.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { User, UserManager } from 'oidc-client-ts'
-
-import { AuthSettings, mergeAuthSettings } from './AuthSettings'
-import { toStringScope } from './utils/toStringScope'
-import { createMockUser, MockUser } from './createMockUser'
-
-let authSettings: AuthSettings | null = null
-let userManager: UserManager | null = null
-
-export const getUserManager = (): UserManager => {
- if (userManager === null) {
- throw new Error('Tried to access user manager before calling configure')
- }
- return userManager
-}
-
-export const getAuthSettings = (): AuthSettings => {
- if (authSettings === null) {
- throw new Error('Tried to access auth settings before calling configure')
- }
- return authSettings
-}
-
-export const configure = (settings: AuthSettings) => {
- authSettings = mergeAuthSettings(settings)
-
- userManager = new UserManager({
- ...authSettings,
- scope: toStringScope(settings.scope),
- redirect_uri: `${authSettings.baseUrl}${authSettings.redirectPath}`,
- })
-
- return userManager
-}
-
-export const configureMock = (user?: MockUser) => {
- authSettings = mergeAuthSettings({
- client_id: 'test-client',
- authority: 'https://innskra.island.is',
- })
-
- const userInfo = createMockUser(user)
- const empty = () => {
- /* intentionally empty */
- }
-
- userManager = {
- getUser(): Promise {
- return Promise.resolve(userInfo)
- },
- signinSilent(): Promise {
- return Promise.resolve(userInfo)
- },
- signinRedirect: empty,
- events: {
- addUserSignedOut: empty,
- addUserLoaded: empty,
- removeUserLoaded: empty,
- removeUserSignedOut: empty,
- },
- } as unknown as UserManager
-}
-
-export { User, UserManager }
diff --git a/libs/auth/react/src/lib/utils/tinyMemoize.spec.ts b/libs/auth/react/src/lib/utils/tinyMemoize.spec.ts
deleted file mode 100644
index e427cfc099a6..000000000000
--- a/libs/auth/react/src/lib/utils/tinyMemoize.spec.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { tinyMemoize } from './tinyMemoize'
-
-type ResolveFn = (value?: number | PromiseLike) => void
-
-describe('tinyMemoize', () => {
- let resolve: ResolveFn
- let slowFunction: jest.Mock
- let memoizedFunction: () => Promise
-
- beforeEach(() => {
- // arrange
- slowFunction = jest.fn(
- () =>
- new Promise((res) => {
- resolve = res
- }),
- )
- memoizedFunction = tinyMemoize(slowFunction)
- })
-
- it("memoizes calls to an async function while it's running", async () => {
- // arrange
- const value = Math.random()
-
- // act
- const promise1 = memoizedFunction()
- const promise2 = memoizedFunction()
- resolve(value)
- const results = await Promise.all([promise1, promise2])
-
- // assert
- expect(slowFunction).toHaveBeenCalledTimes(1)
- expect(promise1).toBe(promise2)
- expect(results).toStrictEqual([value, value])
- })
-
- it('stops memoizing as soon as the async function finishes', async () => {
- // arrange
- const value1 = Math.random()
- const value2 = value1 + 0.1
-
- // act
- const promise1 = memoizedFunction()
- resolve(value1)
- const result1 = await promise1
-
- const promise2 = memoizedFunction()
- resolve(value2)
- const result2 = await promise2
-
- // assert
- expect(slowFunction).toHaveBeenCalledTimes(2)
- expect(promise1).not.toBe(promise2)
- expect(result1).toEqual(value1)
- expect(result2).toEqual(value2)
- })
-})
diff --git a/libs/auth/react/src/lib/utils/tinyMemoize.ts b/libs/auth/react/src/lib/utils/tinyMemoize.ts
deleted file mode 100644
index 90bf5e40bf20..000000000000
--- a/libs/auth/react/src/lib/utils/tinyMemoize.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Makes sure there's only one call to an async function active at any time.
- */
-export const tinyMemoize = (asyncFunction: () => Promise) => {
- let lastPromise: Promise | null
- return () => {
- if (!lastPromise) {
- lastPromise = asyncFunction()
- lastPromise.finally(() => {
- lastPromise = null
- })
- return lastPromise
- }
-
- return lastPromise
- }
-}
diff --git a/libs/auth/react/src/lib/utils/toStringScope.spec.ts b/libs/auth/react/src/lib/utils/toStringScope.spec.ts
deleted file mode 100644
index 928bfca6f130..000000000000
--- a/libs/auth/react/src/lib/utils/toStringScope.spec.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { toStringScope } from './toStringScope'
-
-describe('toStringScope', () => {
- it('should return a string for an array of scope', () => {
- expect(toStringScope(['scope1', 'scope2'])).toBe('scope1 scope2')
- })
-
- it('should return an empty string when no scope is defined', () => {
- expect(toStringScope()).toBe('')
- expect(toStringScope([])).toBe('')
- })
-})
diff --git a/libs/auth/react/src/lib/utils/toStringScope.ts b/libs/auth/react/src/lib/utils/toStringScope.ts
deleted file mode 100644
index 50730e02b5b4..000000000000
--- a/libs/auth/react/src/lib/utils/toStringScope.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export const toStringScope = (array?: string[]): string =>
- (array ?? []).join(' ')
diff --git a/libs/auth/react/test/setup.ts b/libs/auth/react/test/setup.ts
deleted file mode 100644
index d6e27b1da068..000000000000
--- a/libs/auth/react/test/setup.ts
+++ /dev/null
@@ -1 +0,0 @@
-import '@vanilla-extract/css/disableRuntimeStyles'
diff --git a/libs/auth/react/tsconfig.json b/libs/auth/react/tsconfig.json
deleted file mode 100644
index 45d3d172fde4..000000000000
--- a/libs/auth/react/tsconfig.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "extends": "../../../tsconfig.base.json",
- "compilerOptions": {
- "jsx": "react-jsx",
- "allowJs": true
- },
- "files": [],
- "include": [],
- "references": [
- {
- "path": "./tsconfig.lib.json"
- },
- {
- "path": "./tsconfig.spec.json"
- }
- ]
-}
diff --git a/libs/auth/react/tsconfig.lib.json b/libs/auth/react/tsconfig.lib.json
deleted file mode 100644
index 7da3e9d24116..000000000000
--- a/libs/auth/react/tsconfig.lib.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "outDir": "../../../dist/out-tsc",
- "types": ["node"]
- },
- "files": [
- "../../../node_modules/@nx/react/typings/cssmodule.d.ts",
- "../../../node_modules/@nx/react/typings/image.d.ts"
- ],
- "exclude": [
- "**/*.spec.ts",
- "**/*.test.ts",
- "**/*.spec.tsx",
- "**/*.test.tsx",
- "jest.config.ts"
- ],
- "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
-}
diff --git a/libs/auth/react/tsconfig.spec.json b/libs/auth/react/tsconfig.spec.json
deleted file mode 100644
index e1535ba9d07c..000000000000
--- a/libs/auth/react/tsconfig.spec.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "outDir": "../../../dist/out-tsc",
- "module": "commonjs",
- "types": ["jest", "node"]
- },
- "include": [
- "**/*.spec.ts",
- "**/*.test.ts",
- "**/*.spec.tsx",
- "**/*.test.tsx",
- "**/*.spec.js",
- "**/*.test.js",
- "**/*.spec.jsx",
- "**/*.test.jsx",
- "**/*.d.ts",
- "jest.config.ts"
- ]
-}
diff --git a/libs/island-ui/storybook/config/main.ts b/libs/island-ui/storybook/config/main.ts
index 3c9e5ccccacd..051bf8baecdd 100644
--- a/libs/island-ui/storybook/config/main.ts
+++ b/libs/island-ui/storybook/config/main.ts
@@ -75,7 +75,6 @@ const config: StorybookConfig = {
'@island.is/application/ui-components': rootDir(
'../../../application/ui-components/src',
),
- '@island.is/auth/react': rootDir('../../../auth/react/src'),
'@island.is/shared/constants': rootDir('../../../shared/constants/src'),
'@island.is/shared/form-fields': rootDir(
'../../../shared/form-fields/src',
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 030262426294..7be0f1c28845 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -574,7 +574,6 @@
"@island.is/application/utils": ["libs/application/utils/src/index.ts"],
"@island.is/auth-api-lib": ["libs/auth-api-lib/src/index.ts"],
"@island.is/auth-nest-tools": ["libs/auth-nest-tools/src/index.ts"],
- "@island.is/auth/react": ["libs/auth/react/src/index.ts"],
"@island.is/auth/scopes": ["libs/auth/scopes/src/index.ts"],
"@island.is/auth/shared": ["libs/auth/shared/src/index.ts"],
"@island.is/cache": ["libs/cache/src/index.ts"],