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

ADFS tweaks #1538

Merged
merged 8 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ WORKDIR /usr/src/app
# --build-arg COMMIT=$(git rev-parse HEAD) \
# --build-arg VECTOR_TILE_URL=<url of the vector service> \
# --build-arg MAPTILER_STYLE_KEY=<maptiler style key> \
# --build-arg KEYCLOAK_ID=<keycloak client id> \
# --build-arg KEYCLOAK_SECRET=<keycloak secret> \
# --build-arg KEYCLOAK_ISSUER=<keycloak issuer> \
# --build-arg ADFS_ID=<adfs client id> \
# --build-arg ADFS_SECRET=<adfs secret> \
# --build-arg ADFS_ISSUER=<adfs issuer> \
# --build-arg NEXTAUTH_SECRET=<nextauth secret> \
# --build-arg NEXTAUTH_URL=<nextauth url>
ARG COMMIT
ARG VECTOR_TILE_URL
ARG MAPTILER_STYLE_KEY
ARG KEYCLOAK_ID
ARG KEYCLOAK_SECRET
ARG KEYCLOAK_ISSUER
ARG ADFS_ID
ARG ADFS_SECRET
ARG ADFS_ISSUER
ARG NEXTAUTH_SECRET
ARG NEXTAUTH_URL

Expand All @@ -32,9 +32,9 @@ ENV NODE_OPTIONS=--max_old_space_size=2048
ENV NEXT_PUBLIC_COMMIT=$COMMIT
ENV NEXT_PUBLIC_BASE_VECTOR_TILE_URL=$VECTOR_TILE_URL
ENV NEXT_PUBLIC_MAPTILER_STYLE_KEY=$MAPTILER_STYLE_KEY
ENV KEYCLOAK_ID=$KEYCLOAK_ID
ENV KEYCLOAK_SECRET=$KEYCLOAK_SECRET
ENV KEYCLOAK_ISSUER=$KEYCLOAK_ISSUER
ENV ADFS_ID=$ADFS_ID
ENV ADFS_SECRET=$ADFS_SECRET
ENV ADFS_ISSUER=$ADFS_ISSUER
ENV NEXTAUTH_SECRET=$NEXTAUTH_SECRET
ENV NEXTAUTH_URL=$NEXTAUTH_URL
ENV PORT 3000
Expand Down
49 changes: 13 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,17 @@ Once the application's set up, you can start the development server with

```sh
yarn dev
yarn dev:ssl # If you are working with the login process
```

> ℹ️ When using the authentication, you need to use https otherwise you'll experience an SSL
> error when the authentication provider redirects you back to the app after login. You
> can either remove the trailing s in the URL after the redirection, or use the `yarn dev:ssl`
> command to use HTTPs for the development server.

> 👉 In [Visual Studio Code](https://code.visualstudio.com/), you also can run the **default build task** (CMD-SHIFT-B) to start the dev server, database server, and TypeScript checker (you'll need [Nix](https://nixos.org) for that to work).

To run the application with debugging enabled through vscode, make sure the dev server is running and the click the "Run and Debug" button in the sidebar (CMD-SHIFT-D). Then select the "Launch Chrome" configuration. This will open a new Chrome window with the dev tools open. You can now set breakpoints in the code and they will be hit.
To run the application with debugging enabled through VSCode, make sure the dev server is running and the click the "Run and Debug" button in the sidebar (CMD-SHIFT-D). Then select the "Launch Chrome" configuration. This will open a new Chrome window with the dev tools open. You can now set breakpoints in the code and they will be hit.

### Postgres database

Expand Down Expand Up @@ -102,7 +108,7 @@ New versions of `package.json` are built on GitLab CI into a separate image that
yarn version
```

This will prompt for a new version. The `postversion` script will automatically try to push the created version tag to the origin repo.
This will prompt for a new version. The `postversion` script will automatically try to push the created version tag to the origin repository.

## Deployment

Expand Down Expand Up @@ -235,40 +241,11 @@ After the HAR file has been recorded, use [har-to-k6](https://k6.io/docs/test-au

## Authentication

Authentication by eIAM through a Keycloak instance.
We use Next-auth to integrate our application with Keycloak.
See https://next-auth.js.org/providers/keycloak for documentation.
Authentication is provided by the Swiss federal government's eIAM through ADFS.
We use Next-auth to integrate our application with it, through a [custom Provider](app/auth-providers/adfs.ts).

### Locally

The easiest way is to run Keycloak via Docker.

```
docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:19.0.3 start-dev
```

⚠️ After creating the container via the above command, if you stop it, restart the container via the docker UI so that you re-use the
same storage, otherwise you'll have to reconfigure Keycloak.

To configure Keycloak:

- Access the [Keycloak admin][keycloak-admin] (login, password: "admin", "admin")
- Create client application
- Via import: [Keycloak][keycloak-admin] > Clients > Import client
- Use the exported client `keycloak-visualize-client-dev.json`
- Manually: [Keycloak][keycloak-admin] > Clients > Create client
- id: "visualize"
- Choose OpenIDConnect
- In next slide, toggle "Client Authentication" on
- Configure redirect URI on client
- Root URL: `http://localhost:3000`
- Redirect URI: `/api/auth/callback/keycloak`
- Create a user
- Set a password to the user (in Credentials tab)
- Set environment variables in `.env.local`
- KEYCLOAK_ID: "visualize"
- KEYCLOAK_SECRET: From [Keycloak][keycloak-admin] > Clients > visualize > Credentials > Client secret
- KEYCLOAK_ISSUER: http://localhost:8080/realms/master
- NEXTAUTH_SECRET: Any string, can be "secret" locally

[keycloak-admin]: http://localhost:8080/admin/master/console/#/
You can use the ref eIAM. ADFS environment variables should be configured in your
`.env.local` file. You'll find those secret variables in our shared 1Password in
the "Visualize.admin .env.local" entry.
6 changes: 2 additions & 4 deletions app/auth-providers/adfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export default function ADFS<P extends ADFSProfile>(

idToken: true,

// @ts-ignore
async profile(profile: P, tokens) {
// Usually the user only has one role, which is a string.
let role = profile.role;
Expand All @@ -59,18 +58,17 @@ export default function ADFS<P extends ADFSProfile>(
if (opRole != undefined) {
role = opRole;
}
// Otherwise, take the first occurance in the list.
// Otherwise, take the first occurence in the list.
else {
role = profile.role[0];
}
}

return {
id: profile.sub,
name: profile.unique_name,
name: `${profile.given_name} ${profile.family_name}`,
email: profile.email,
role: role,

idToken: tokens.id_token,
};
},
Expand Down
6 changes: 3 additions & 3 deletions app/domain/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ export const GA_TRACKING_ID =
*/

export const DATABASE_URL = process.env.DATABASE_URL;
export const KEYCLOAK_ID = process.env.KEYCLOAK_ID;
export const KEYCLOAK_SECRET = process.env.KEYCLOAK_SECRET;
export const KEYCLOAK_ISSUER = process.env.KEYCLOAK_ISSUER;
export const ADFS_ID = process.env.ADFS_ID;
export const ADFS_SECRET = process.env.ADFS_SECRET;
export const ADFS_ISSUER = process.env.ADFS_ISSUER;

/**
* Variables set at **BUILD TIME** through `NEXT_PUBLIC_*` variables. Available on the client and server.
Expand Down
2 changes: 1 addition & 1 deletion app/login/components/login-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const LoginMenu = () => {
variant="text"
color="primary"
size="small"
onClick={() => signIn("keycloak")}
onClick={() => signIn("adfs")}
>
Sign in
</Button>
Expand Down
21 changes: 9 additions & 12 deletions app/pages/api/auth/[...nextauth].ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import NextAuth, { NextAuthOptions } from "next-auth";

import ADFS from "@/auth-providers/adfs";
import { ensureUserFromSub } from "@/db/user";
import { KEYCLOAK_ID, KEYCLOAK_ISSUER, KEYCLOAK_SECRET } from "@/domain/env";
import { ADFS_ID, ADFS_ISSUER, ADFS_SECRET } from "@/domain/env";
import { truthy } from "@/domain/types";

import type { NextApiRequest, NextApiResponse } from "next";

const providers = [
KEYCLOAK_ID && KEYCLOAK_SECRET && KEYCLOAK_ISSUER
ADFS_ID && ADFS_SECRET && ADFS_ISSUER
? ADFS({
wellKnown: `${KEYCLOAK_ISSUER}/.well-known/openid-configuration`,
clientId: KEYCLOAK_ID,
clientSecret: KEYCLOAK_SECRET,
authorizeUrl: `${KEYCLOAK_ISSUER}/protocol/openid-connect/auth`,
issuer: KEYCLOAK_ISSUER,
token: `${KEYCLOAK_ISSUER}/protocol/openid-connect/token`,
userinfo: `${KEYCLOAK_ISSUER}/protocol/openid-connect/userinfo`,
wellKnown: `${ADFS_ISSUER}/.well-known/openid-configuration`,
clientId: ADFS_ID,
clientSecret: ADFS_SECRET,
authorizeUrl: `${ADFS_ISSUER}/protocol/openid-connect/auth`,
issuer: ADFS_ISSUER,
token: `${ADFS_ISSUER}/protocol/openid-connect/token`,
userinfo: `${ADFS_ISSUER}/protocol/openid-connect/userinfo`,
checks: ["pkce", "state"],
client: {
token_endpoint_auth_method: "none",
Expand All @@ -33,9 +33,6 @@ export const nextAuthOptions = {
* on the session.
*/
session: async ({ session, token }) => {
console.log("Session:", session);
console.log("Token:", token);

if (session.user && token.sub) {
session.user.sub = token.sub;
const user = await ensureUserFromSub(token.sub, token.name);
Expand Down
2 changes: 1 addition & 1 deletion app/sentry.server.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if (process.env.NODE_ENV !== "development") {
tracesSampleRate: 0.1,
instrumenter: {
patch: (mod, path, logger) => {
// Ignore auth calls to prevent 405 Keycloak errors.
// Ignore auth calls to prevent 405 authentication errors.
if (path?.includes("auth")) {
return null;
}
Expand Down
6 changes: 3 additions & 3 deletions scripts/docker-build-push.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ docker build \
--build-arg COMMIT=$CI_COMMIT_SHA \
--build-arg MAPTILER_STYLE_KEY=$MAPTILER_STYLE_KEY \
--build-arg VECTOR_TILE_URL=$VECTOR_TILE_URL \
--build-arg KEYCLOAK_ID=$KEYCLOAK_ID \
--build-arg KEYCLOAK_SECRET=$KEYCLOAK_SECRET \
--build-arg KEYCLOAK_ISSUER=$KEYCLOAK_ISSUER \
--build-arg ADFS_ID=$ADFS_ID \
--build-arg ADFS_SECRET=$ADFS_SECRET \
--build-arg ADFS_ISSUER=$ADFS_ISSUER \
--build-arg NEXTAUTH_SECRET=$NEXTAUTH_SECRET \
--build-arg NEXTAUTH_URL=$NEXTAUTH_URL \
$(echo $DOCKER_IMAGE_TAGS | tr ' ' '\n' | xargs -n 1 -I {} echo "-t {}" ) .
Expand Down
Loading