My objective now is to configure Keycloak to test a 2-factor authentication scenario with a Yubikey.
The token I've got is a Yubikey 4 , previously known as a FIDO U2F token, and since the publication of the FIDO2 specification is now known as Webauthn CTAP1 (Client to Authenticator Protocol 1) Authenticator.
This is an older token but it will do the job. Part of my objective with this mini-project to is to determine if it's worth spending money on a stack of FIDO2 hardware tokens.
So let's go through the steps. My sources for this are the Keycloak documentation and this video for an older version of Keycloak by Stian Thorgersen the project lead. Blink and you'll miss it.
You'll find my own video of the process at the end.
1) Create a realm
Keycloak is deceptively simple when you first discover it. And then you start delving into the options and quickly realise you have no idea what half the stuff does.
2) Copy browser authentication flow
We then go to the Authentication menu when the authentication Flows are selected by default.
Make sure the "Browser" flow is selected, and click the copy button. Give it a name.
3) Authentication flows are the control logic for determining how any particular authentication context is treated. We need to leave Cookie and Identity Provider Redirector alone because they will allow us to authenticate a user who has already authenticated with some other method.
Out of the box the Browser flow is configured with conditional 2FA if the user has already configured a TOTP in their account. For our demo purposes we're going to disable that and force them to register a token.
- Choose the action to delete "Webauthn Browser - Conditional OTP"
- "Add execution" on the line "Browser Webauthn Forms"
- Choose "WebAuthn Authenticator" and save
- Change the Requirement on the new WebAuthn Authenticator line to "Required"
4) Next we need to make users register their shiny token so they can log in.
- Select the "Required Actions" menu
- Click "Register" and then add the "Webauthn Register" option.
- In this case I am a FIDO2 CATP1 extremist and will not tolerate any other kind of 2FA so I disable the "Configure OTP" option.
- Move the Webauthn Register option up to the top and select as the "Default Action"
5) Next I need to configure the WebAuthn Policy. Lucky me.
- Go to the Webauthn Policy menu. There are a few critical options here I need to configure.
- I specify the hostname I put in my container's TLS certificate in the "Relying Party ID" option. I also added this hostname to my hosts file (last blog post updated...)
- "Attestation Conveyance Preference" changes the behaviour of the webauthn client during registration and how Keycloak obtains the public key used for verifying authentication assertions, and essentially determines how the "Relying Party", that's Keycloak" can trust the crypto being used. I'll set this to "direct" which increases the cost/time of the registration in exchange for a stricter set of specs. I'm going to investigate Attestation Statements at a later date.
- Some functionality is only available with FIDO2 specification authenticators, for example it's possible to specify AAGUIDs and so limit what kind of tokens users are allowed to register. I'm using an older token so I'll leave the other settings on default.
6) Now we have Webauthn configured we need to bind our authentication flow to Browser logins.
- Go to the "Bindings" menu
- Change the Browser Flow binding to "Browser webauthn" or whatever you specified in step 2
7) In this demo I'm going to allow users to register to the realm and create an account. These could be existing accounts mapped to LDAP, AD or just created locally within the Keycloak realm.
- Go to "Realm Settings" and select the "Login" menu
- Turn User Registration on and save
8) Now we're going to try and use it.
- Go to the "Clients" menu and copy the Base URL for the "account" client ID.
- The aim is to open this link in an unauthenticated context, so you can either open it in a private browsing window or use another browser or just logout as admin.
- I register a new user bar@foo, username barf
- Upon clicking register, my browser prompts me to provide a FIDO authenticator
- Then it asks me to touch the authenticator to confirm I want to register it
- Then the browser webauthn client asks to directly access the authenticator. This is to generate the Attestation Statement.
- Give it a friendly name for Keycloak to register it under
- It's done!
- Logging out and then back into the realm account setting page with the account we just created should request another touch on the authenticator after the Keycloak username/password.
- Please feel free to message me with any corrections or improvements. I'm still just figuring all this stuff out.