Giter Site home page Giter Site logo

keycloak-magic-link's People

Contributors

akharlamov avatar arnaud-j avatar redabourial avatar tfcornerstone avatar tstec-polypoly avatar ulrich avatar vanerac avatar xgp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

keycloak-magic-link's Issues

How do I contribute to the repo?

Hi,

I have made some changes where it is possible to configure some of the defaults when requesting a magic link from keycloak instead of the API (e.g. lifetime of the link)

How do I contribute this as a PR for your review?

Magic Link for authentication session continuation

Feature request for a magic link that can cause a continuation of an authentication session already underway.

Use case

  1. User authenticates and is challenged by sending a magic link to email, using a custom Authenticator
  2. Page polls for completion of challenge (e.g. is an auth note set/unset). This can just be a custom FTL with a javascript reload. Page tells them not to close the page.
  3. Magic link is an action token that encodes the authentication session ID and tab ID and client ID
  4. User clicks on link, potentially in a separate device. Page gives a success message and tells them to return to the initial page. If it is the same device, it also gives them a link to go to the application (this just joins the authentication session and continues with a success).
  5. Action token handler looks up the authentication session by ID and tab ID and client ID and allows it to continue (by setting an Auth Note)
  6. Polling picks up that the link has been clicked (by checking the Auth Note), and automatically continues the authentication with a success.
  7. After a configurable amount of time, the Authenticator gives up and provides an error message to the user that the link has expired.

relevant KC code

AuthenticationSessionProvider p = session.authenticationSessions();
RootAuthenticationSessionModel m = p.getRootAuthenticationSession( realm,  authenticationSessionId);
// look up clientByClientId
AuthenticationSessionModel asm = m.getAuthenticationSession( client,  tabId)

Default group assignment after user creation

I would like to assign a user to a specific group using the magic link authenticator.

A possiblie solution could be to add an addition property to the actionToken containg a groupId or a group path
and adding the user to this group in the TokenHandler.

What do you think about this approach?
If you think this is a useful feature I would also be willing to work on a pull request.

Send OTP codes via API

We would like to know how to use the API to trigger the sending of an OTP code via email, just like we can do with the Magic Links:

POST http://localhost:8080/realms/myrealm/magic-link

{
  "email": "myemailaddress",
  "client_id": "myclientid",
  "redirect_uri": "http://localhost:8080/",
  "expiration_seconds": 3600,
  "send_email": true
}

Thanks!

Prebuilt `.jar` files

Hi,
I was looking into building the .jar file via GitHub actions when I discovered that the workflow is already doing that. It worked for me to download the new .jar from here (found by going to https://s01.oss.sonatype.org, searching for keycloak magic link, selecting the latest version, clicking on the keycloak-magic-link-0.19.jar in the tree at the bottom and clicking download on the right.
Maybe we could
a) link this page / put some docs in the readme
b) also upload that artifact to GitHub releases so it can be discovered more easily?

In my opinion this would make it easier since people don't have to install java (or hassle with Codespaces which can sometimes be a problem as we have seen) and can just download the .jar.

What do you think?

Issues when configuring provider plugin

Hey, hoping to get some help configuring the provider. Sorry in advance for my ignorance of Java and Keycloak...

My environment:

I made the following steps to configure:

Screen Shot 2022-08-29 at 14 13 11

Screen Shot 2022-08-29 at 14 13 50

Screen Shot 2022-08-29 at 14 26 16

Screen Shot 2022-08-29 at 14 16 02

Screen Shot 2022-08-29 at 14 20 09

Screen Shot 2022-08-29 at 14 20 15

Screen Shot 2022-08-29 at 14 20 22

Screen Shot 2022-08-29 at 14 25 17

I then tested by navigating a private window to https://localhost:8037/realms/test/account/#/ as seen here:
Screen Shot 2022-08-29 at 16 05 53

Then I clicked "Sign in" which resulted in:
Screen Shot 2022-08-29 at 16 05 58

The previous action triggered the following message in the Keycloak logs:

keycloak | 2022-08-29 14:09:03,245 WARN  [org.keycloak.services] (executor-thread-50) KC-SERVICES0013: Failed authentication: org.keycloak.authentication.AuthenticationFlowException
keycloak | 	at org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:1038)
keycloak | 	at org.keycloak.authentication.AuthenticationProcessor.authenticate(AuthenticationProcessor.java:892)
keycloak | 	at org.keycloak.protocol.AuthorizationEndpointBase.handleBrowserAuthenticationRequest(AuthorizationEndpointBase.java:151)
keycloak | 	at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildAuthorizationCodeAuthorizationResponse(AuthorizationEndpoint.java:338)
keycloak | 	at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.process(AuthorizationEndpoint.java:194)
keycloak | 	at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildGet(AuthorizationEndpoint.java:112)
keycloak | 	at jdk.internal.reflect.GeneratedMethodAccessor644.invoke(Unknown Source)
keycloak | 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
keycloak | 	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
keycloak | 	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
keycloak | 	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
keycloak | 	at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
keycloak | 	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
keycloak | 	at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
keycloak | 	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
keycloak | 	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
keycloak | 	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
keycloak | 	at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
keycloak | 	at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
keycloak | 	at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:183)
keycloak | 	at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
keycloak | 	at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
keycloak | 	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
keycloak | 	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
keycloak | 	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
keycloak | 	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
keycloak | 	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
keycloak | 	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
keycloak | 	at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
keycloak | 	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
keycloak | 	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82)
keycloak | 	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42)
keycloak | 	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
keycloak | 	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
keycloak | 	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
keycloak | 	at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:67)
keycloak | 	at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:55)
keycloak | 	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
keycloak | 	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
keycloak | 	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
keycloak | 	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:380)
keycloak | 	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:358)
keycloak | 	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
keycloak | 	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
keycloak | 	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
keycloak | 	at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$1(QuarkusRequestFilter.java:71)
keycloak | 	at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:159)
keycloak | 	at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
keycloak | 	at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:157)
keycloak | 	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:543)
keycloak | 	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
keycloak | 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
keycloak | 	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
keycloak | 	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
keycloak | 	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
keycloak | 	at java.base/java.lang.Thread.run(Thread.java:829)
keycloak |
keycloak | 2022-08-29 14:09:03,249 WARN  [org.keycloak.events] (executor-thread-50) type=LOGIN_ERROR, realmId=test, clientId=account-console, userId=null, ipAddress=172.25.0.1, error=invalid_user_credentials, auth_method=openid-connect, auth_type=code, response_type=code, redirect_uri=https://localhost:8037/realms/test/account/#/, code_id=6e39432e-93a0-4eeb-bc9f-e09babb21a82, response_mode=fragment, authSessionParentId=6e39432e-93a0-4eeb-bc9f-e09babb21a82, authSessionTabId=SK8QgVyzKeI

I also tried a few permutations of the request mentioned in the README.md with the following results:

As suggested in README.md

curl --insecure --request POST https://localhost:8037/auth/realms/test/magic-link \
 --header "Accept: application/json" \
 --header "Content-Type: application/json" \
 --header "Authorization: Bearer" \
 --data '{"email":"[email protected]","client_id":"account-console","redirect_uri":"https://localhost:8037/auth/realms/test/account/","expiration_seconds":3600,"force_create":true,"update_profile":true,"send_email":true}'

# Result
{"error":"RESTEASY003210: Could not find resource for full path: https://localhost:8037/auth/realms/test/magic-link"}%

Fixes redirect URI to what I assume is correct. Tries /realms/test/magic-link as POST path. Guessing this one is closest?

curl --insecure --request POST https://localhost:8037/realms/test/magic-link \
 --header "Accept: application/json" \
 --header "Content-Type: application/json" \
 --header "Authorization: Bearer" \
 --data '{"email":"[email protected]","client_id":"account-console","redirect_uri":"https://localhost:8037/realms/test/account/","expiration_seconds":3600,"force_create":true,"update_profile":true,"send_email":true}'

# Result
{"error":"HTTP 401 Unauthorized"}%

Fixes redirect URI to what I assume is correct. Tries /realms/test/protocol/openid-connect/auth as POST path.

curl --insecure --request POST https://localhost:8037/realms/test/protocol/openid-connect/auth \
 --header "Accept: application/json" \
 --header "Content-Type: application/json" \
 --header "Authorization: Bearer" \
 --data '{"email":"[email protected]","client_id":"account-console","redirect_uri":"https://localhost:8037/realms/test/account/","expiration_seconds":3600,"force_create":true,"update_profile":true,"send_email":true}'

# Result
{"error":"RESTEASY003065: Cannot consume content type"}

Fixes redirect URI to what I assume is correct. Tries /realms/test/protocol/openid-connect/auth/magic-link as POST path.

curl --insecure --request POST https://localhost:8037/realms/test/protocol/openid-connect/auth/magic-link \
 --header "Accept: application/json" \
 --header "Content-Type: application/json" \
 --header "Authorization: Bearer" \
 --data '{"email":"[email protected]","client_id":"account-console","redirect_uri":"https://localhost:8037/realms/test/account/","expiration_seconds":3600,"force_create":true,"update_profile":true,"send_email":true}'

# Result
{"error":"RESTEASY003210: Could not find resource for full path: https://localhost:8037/realms/test/protocol/openid-connect/auth/magic-link"}%

Fixes redirect URI to what I assume is correct. Tries /realms/test/protocol/openid-connect/magic-link as POST path.

curl --insecure --request POST https://localhost:8037/realms/test/protocol/openid-connect/magic-link \
 --header "Accept: application/json" \
 --header "Content-Type: application/json" \
 --header "Authorization: Bearer" \
 --data '{"email":"[email protected]","client_id":"account-console","redirect_uri":"https://localhost:8037/realms/test/account/","expiration_seconds":3600,"force_create":true,"update_profile":true,"send_email":true}'

# Result
{"error":"RESTEASY003210: Could not find resource for full path: https://localhost:8037/realms/test/protocol/openid-connect/magic-link"}%

Installation not working

Hi,
first of all, thanks for this plugin. I'd really like to use it, however, I cannot get it installed (or enabled?).
I'm using the bitnami keycloak docker image. My docker-compose.yml looks like this:

version: '3.3'
services:
  postgresql:
    restart: unless-stopped
    image: bitnami/postgresql
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
      - POSTGRESQL_USERNAME=bn_keycloak
      - POSTGRESQL_DATABASE=bitnami_keycloak
    volumes:
      - 'postgresql_data:/bitnami/postgresql'

  keycloak:
    restart: unless-stopped
    image: bitnami/keycloak
    # enable token-exchange
    environment:
      - KEYCLOAK_EXTRA_ARGS=--features=token-exchange,admin-fine-grained-authz
    # extension jars from ./keycloak-extensions (new for quarkus)
    volumes:
      - ./keycloak-extensions:/opt/bitnami/keycloak/providers
    depends_on:
      - postgresql
    ports:
      - '8081:8080'

volumes:
  postgresql_data:
    driver: local

I've copied the keycloak-magic-link-0.17-SNAPSHOT.jar to ./keycloak-extensions.

However, the /magic-link url returns a {"error":"HTTP 404 Not Found"} and I can't find the Magic Link Step in the UI. I made sure to not be on the master realm.

Keycloak does somehow detect the .jar file, because if I copy both by mvn clean install generated files (keycloak-magic-link-0.17-SNAPSHOT.jar and original-keycloak-magic-link-0.17-SNAPSHOT.jar, the docker logs show:

2023-08-22 10:52:33 2023-08-22 08:52:32,131 INFO  [org.keycloak.common.Profile] (main) Preview features enabled: admin-fine-grained-authz, token-exchange
2023-08-22 10:52:33 2023-08-22 08:52:33,369 WARN  [io.quarkus.arc.deployment.SplitPackageProcessor] (build-2) Detected a split package usage which is considered a bad practice and should be avoided. Following packages were detected in multiple archives: 
2023-08-22 10:52:33 - "io.phasetwo.keycloak.magic.auth.token" found in [/opt/bitnami/keycloak/lib/../providers/keycloak-magic-link-0.17-SNAPSHOT.jar, /opt/bitnami/keycloak/lib/../providers/original-keycloak-magic-link-0.17-SNAPSHOT.jar]
2023-08-22 10:52:33 - "io.phasetwo.keycloak.magic" found in [/opt/bitnami/keycloak/lib/../providers/keycloak-magic-link-0.17-SNAPSHOT.jar, /opt/bitnami/keycloak/lib/../providers/original-keycloak-magic-link-0.17-SNAPSHOT.jar]
2023-08-22 10:52:33 - "io.phasetwo.keycloak.magic.auth" found in [/opt/bitnami/keycloak/lib/../providers/keycloak-magic-link-0.17-SNAPSHOT.jar, /opt/bitnami/keycloak/lib/../providers/original-keycloak-magic-link-0.17-SNAPSHOT.jar]
2023-08-22 10:52:33 - "io.phasetwo.keycloak.magic.representation" found in [/opt/bitnami/keycloak/lib/../providers/keycloak-magic-link-0.17-SNAPSHOT.jar, /opt/bitnami/keycloak/lib/../providers/original-keycloak-magic-link-0.17-SNAPSHOT.jar]
2023-08-22 10:52:33 - "io.phasetwo.keycloak.magic.resources" found in [/opt/bitnami/keycloak/lib/../providers/keycloak-magic-link-0.17-SNAPSHOT.jar, /opt/bitnami/keycloak/lib/../providers/original-keycloak-magic-link-0.17-SNAPSHOT.jar]
2023-08-22 10:52:35 2023-08-22 08:52:35,695 INFO  [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 3975ms

Docker Container logs with only one of the two files (which one should be used by the way?)

2023-08-22 10:46:20 
2023-08-22 10:46:20 keycloak 08:46:20.79 
2023-08-22 10:46:20 keycloak 08:46:20.79 Welcome to the Bitnami keycloak container
2023-08-22 10:46:20 keycloak 08:46:20.79 Subscribe to project updates by watching https://github.com/bitnami/containers
2023-08-22 10:46:20 keycloak 08:46:20.80 Submit issues and feature requests at https://github.com/bitnami/containers/issues
2023-08-22 10:46:20 keycloak 08:46:20.80 
2023-08-22 10:46:20 keycloak 08:46:20.80 INFO  ==> ** Starting keycloak setup **
2023-08-22 10:46:20 keycloak 08:46:20.81 INFO  ==> Validating settings in KEYCLOAK_* env vars...
2023-08-22 10:46:20 /opt/bitnami/scripts/libvalidations.sh: line 245: return: : numeric argument required
2023-08-22 10:46:20 keycloak 08:46:20.82 INFO  ==> Trying to connect to PostgreSQL server postgresql...
2023-08-22 10:46:20 keycloak 08:46:20.83 INFO  ==> Found PostgreSQL server listening at postgresql:5432
2023-08-22 10:46:20 keycloak 08:46:20.84 INFO  ==> Configuring database settings
2023-08-22 10:46:20 keycloak 08:46:20.86 INFO  ==> Enabling statistics
2023-08-22 10:46:20 keycloak 08:46:20.87 INFO  ==> Enabling health endpoints
2023-08-22 10:46:20 keycloak 08:46:20.87 INFO  ==> Configuring http settings
2023-08-22 10:46:20 keycloak 08:46:20.90 INFO  ==> Configuring hostname settings
2023-08-22 10:46:20 keycloak 08:46:20.90 INFO  ==> Configuring cache count
2023-08-22 10:46:20 keycloak 08:46:20.91 INFO  ==> Configuring log level
2023-08-22 10:46:20 keycloak 08:46:20.91 INFO  ==> Configuring proxy
2023-08-22 10:46:20 keycloak 08:46:20.92 INFO  ==> ** keycloak setup finished! **
2023-08-22 10:46:20 keycloak 08:46:20.93 INFO  ==> ** Starting keycloak **
2023-08-22 10:46:21 Updating the configuration and installing your custom providers, if any. Please wait.
2023-08-22 10:46:24 2023-08-22 08:46:21,563 INFO  [org.keycloak.common.Profile] (main) Preview features enabled: admin-fine-grained-authz, token-exchange
2023-08-22 10:46:24 2023-08-22 08:46:23,076 INFO  [org.keycloak.common.Profile] (main) Preview features enabled: admin-fine-grained-authz, token-exchange
2023-08-22 10:46:27 2023-08-22 08:46:27,068 INFO  [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 4387ms
2023-08-22 10:46:29 2023-08-22 08:46:27,836 INFO  [org.keycloak.common.Profile] (main) Preview features enabled: admin-fine-grained-authz, token-exchange
2023-08-22 10:46:29 2023-08-22 08:46:28,258 INFO  [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: Base URL: <unset>, Hostname: <request>, Strict HTTPS: false, Path: <request>, Strict BackChannel: false, Admin URL: <unset>, Admin: <request>, Port: -1, Proxied: true
2023-08-22 10:46:29 2023-08-22 08:46:29,711 WARN  [io.quarkus.agroal.runtime.DataSources] (main) Datasource <default> enables XA but transaction recovery is not enabled. Please enable transaction recovery by setting quarkus.transaction-manager.enable-recovery=true, otherwise data may be lost if the application is terminated abruptly
2023-08-22 10:46:30 2023-08-22 08:46:30,357 WARN  [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2023-08-22 10:46:30 2023-08-22 08:46:30,453 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
2023-08-22 10:46:30 2023-08-22 08:46:30,568 INFO  [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000088: Unable to use any JGroups configuration mechanisms provided in properties {}. Using default JGroups configuration!
2023-08-22 10:46:30 2023-08-22 08:46:30,656 INFO  [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000078: Starting JGroups channel `ISPN`
2023-08-22 10:46:30 2023-08-22 08:46:30,658 INFO  [org.jgroups.JChannel] (keycloak-cache-init) local_addr: 726a0f81-c6b5-42ba-8642-0d0913d3ff28, name: 2c353f136ffd-12467
2023-08-22 10:46:30 2023-08-22 08:46:30,664 WARN  [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the send buffer of socket MulticastSocket was set to 1MB, but the OS only allocated 212.99KB
2023-08-22 10:46:30 2023-08-22 08:46:30,665 WARN  [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the receive buffer of socket MulticastSocket was set to 20MB, but the OS only allocated 212.99KB
2023-08-22 10:46:30 2023-08-22 08:46:30,665 WARN  [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the send buffer of socket MulticastSocket was set to 1MB, but the OS only allocated 212.99KB
2023-08-22 10:46:30 2023-08-22 08:46:30,665 WARN  [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the receive buffer of socket MulticastSocket was set to 25MB, but the OS only allocated 212.99KB
2023-08-22 10:46:30 2023-08-22 08:46:30,674 INFO  [org.jgroups.protocols.FD_SOCK2] (keycloak-cache-init) server listening on *.27504
2023-08-22 10:46:30 2023-08-22 08:46:30,967 INFO  [org.keycloak.broker.provider.AbstractIdentityProviderMapper] (main) Registering class org.keycloak.broker.provider.mappersync.ConfigSyncEventListener
2023-08-22 10:46:32 2023-08-22 08:46:32,682 INFO  [org.jgroups.protocols.pbcast.GMS] (keycloak-cache-init) 2c353f136ffd-12467: no members discovered after 2006 ms: creating cluster as coordinator
2023-08-22 10:46:32 2023-08-22 08:46:32,689 INFO  [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000094: Received new cluster view for channel ISPN: [2c353f136ffd-12467|0] (1) [2c353f136ffd-12467]
2023-08-22 10:46:32 2023-08-22 08:46:32,699 INFO  [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000079: Channel `ISPN` local address is `2c353f136ffd-12467`, physical addresses are `[172.20.0.6:43040]`
2023-08-22 10:46:33 2023-08-22 08:46:33,030 INFO  [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: 2c353f136ffd-12467, Site name: null
2023-08-22 10:46:33 2023-08-22 08:46:33,829 INFO  [io.quarkus] (main) Keycloak 22.0.1 on JVM (powered by Quarkus 3.2.0.Final) started in 6.663s. Listening on: http://0.0.0.0:8080
2023-08-22 10:46:33 2023-08-22 08:46:33,830 INFO  [io.quarkus] (main) Profile dev activated. 
2023-08-22 10:46:33 2023-08-22 08:46:33,830 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, logging-gelf, micrometer, narayana-jta, reactive-routes, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, vertx]
2023-08-22 10:46:33 2023-08-22 08:46:33,837 WARN  [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.

Any idea what I might be missing?

Missing state parameter in response from identity provider.

We are testing the keycloak-magic-link, and everything is fine when we use that in a browser flow in an IDB realm that the application connects to validate the user, as in the image below.

image

But in our scenario, we need to provide more than one login option to our users. For that, we configure multiple identity providers in an IDB realm, and we are creating another realm for the magic link to act as an idP. The configuration is like the image below.

image

These are the steps when we try to connect our example application (SP).

  1. User clicks on the MLIDP idp button.
    image

  2. User informs the email and submits it.
    image

  3. User clicks on the email received by email.
    image

  4. User gets an error as a response
    image

To check that we have configured the idP configuration in the IDB realm and the client in the MLIDP realm, we have changed the MLIDP realm client flow to the standard browser flow, as shown in the image below. After test, we can log in successfully.

image

There is one issue opened that the state is mentioned, but we don't know whether it is related to the issue we got.
Magic link doesn't support PKCE or state/nonce values

The keycloak version used during tests was 18.0.1.

Need help setting up magic link with Grafana

I'm facing a weird issue when trying to use magic links with Grafana. When I click on the magic link Grafana gives me a "missing saved state" exception (see screenshot below)

image

There is nothing useful in the grafana logs and the weird thing is that the authentication has happened successfully, even with this error. If I open the root url in the browser now, I find myself logged in with the desired user.

Relevant config from the grafana setup I'm using for testing this

[auth]
disable_login_form = true
oauth_auto_login = true

[auth.generic_oauth]
allow_sign_up = true
api_url = "<keycloak_server_url>/auth/realms/<realm>/protocol/openid-connect/userinfo"
auth_url = "/auth/realms/<realm>/protocol/openid-connect/auth"
client_id = "<redacted>"
client_secret = "<redacted>"
enabled = true
login_attribute_path = "preferred_username"
name = "Keycloak"
scopes = "openid email"
token_url = "<keycloak_server_url>/auth/realms/<realm>/protocol/openid-connect/token

I'll be happy to provide any other info. Thanks in advance!

Building for Bitnami container

Docker newb here.

I grabbed the latest source from this repo.

Did a mvn clean install locally (Debian)

I then uploaded the resulting .jar to /opt/bitnami/keycloak/providers/keycloak-magic-link-0.13.jar

In docker-compose I have

` keycloak:
image: docker.io/bitnami/keycloak:${SOFTWARE_VERSION_TAG}
container_name: keycloak
restart: always
env_file:
- .env

volumes:
- ./keycloak-magic-link-0.13.jar:/opt/bitnami/keycloak/providers/keycloak-magic-link-0.13.jar
ports:
  - '172.17.0.1:8080:8080'
`

When I restart the container I get

ay 31 15:52:45 keycloak-ownership-clone-u4111 57c55751cd7c[2953]: #033[38;5;6mkeycloak #033[38;5;5m15:52:45.76 #033[0m#033[38;5;2mINFO #033[0m ==> ** Starting keycloak **
May 31 15:52:46 keycloak-ownership-clone-u4111 57c55751cd7c[2953]: Exception in thread "main" java.io.EOFException
May 31 15:52:46 keycloak-ownership-clone-u4111 57c55751cd7c[2953]: #011at java.base/java.io.DataInputStream.readBoolean(DataInputStream.java:250)
May 31 15:52:46 keycloak-ownership-clone-u4111 57c55751cd7c[2953]: #011at io.quarkus.bootstrap.runner.SerializedApplication.read(SerializedApplication.java:119)

Test with Keycloak App not redirecting correctly

Hello,

I have installed this provider in my local Keycloak, and I'm using the Keycloak test app to make tests : https://www.keycloak.org/app/

When using another provider for the magic link(the "experiment" you link, that uses magic-link "session based", as opposed to "action-token based"), I am logged-in instantly after clicking the magic-link in the email.

When using this provider (with action-token), when I click the link, I am presented with this screen again :

image

And I have to click again on "Sign In", then I'm logged in. This did not happen with the version of the magic link that did not use action-tokens.

I have looked into the code and I suppose that this part of the code is doing this :
String nextAction = AuthenticationManager.nextRequiredAction( tokenContext.getSession(), authSession, tokenContext.getRequest(), tokenContext.getEvent()); return AuthenticationManager.redirectToRequiredActions( tokenContext.getSession(), tokenContext.getRealm(), authSession, tokenContext.getUriInfo(), nextAction);

But I have not found how to modify it to have the behaviour I want.
Thank you

Encoding of messages_xx.properties

Hello there!

I am struggling to make working email template with cyrillic translation messages.

magicLinkSubject=ะ ะตะณะธัั‚ั€ะฐั†ะธั ะฒ program
emailTemplateProvider
          .setRealm(realm)
          .setUser(user)
          .setAttribute("realmName", realmName)
          .send("magicLinkSubject", subjAttr, "magic-link-email.ftl", bodyAttr);

When trying to do with default file encoding, I was getting question marks instead cyrillic characters, eg: ?????? ? program.

After I did some transformations of the file, I've got that subjectFormatKey stopped to be used from resourse's file and instead it is using just arg's passed string "magicLinkSubject" in subject of sent email. So that fixed my initial problem with using messages.properties file, I've just written plain subject instead format key

 emailTemplateProvider
          .setRealm(realm)
          .setUser(user)
          .setAttribute("realmName", realmName)
          .send("ะ ะตะณะธัั‚ั€ะฐั†ะธั ะฒ program", subjAttr, "magic-link-email.ftl", bodyAttr);

But I am not satisfied, because I think this solution is not correct, can you help me to make it working using messages_xx.resources file?

Thanks for any help!

Failed authentication: java.lang.IllegalStateException: Magic links not allowed for master realm

I have setup ML in a docker container:

ARG KEYCLOAK_VERSION=23.0.4

FROM quay.io/keycloak/keycloak:${KEYCLOAK_VERSION} as builder

# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true

# for demonstration purposes only, please make sure to use proper certificates in production instead
# RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
COPY ./keycloak-plugins/keycloak-magic-link-0.23.jar /opt/keycloak/providers/magiclink.jar
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:${KEYCLOAK_VERSION}
COPY --from=builder /opt/keycloak/ /opt/keycloak/

# change these values to point to a running oracle instance
ENV KC_DB=oracle
ENV KC_DB_URL=jdbc:oracle:thin:@someserver
ENV KC_DB_USERNAME=KEYCLOAK
ENV KC_DB_PASSWORD=somePassword
ENV KC_db_SCHEMA=KEYCLOAK
ENV KC_HOSTNAME=localhost

ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

# stรฅ i C:\Projects\external-idp
# docker build -f scripts/kc-image/Dockerfile . --tag kc:latest
# docker run -d -p 8088:8080 --name kc-custom kc:latest start-dev

Picture of login flow

image

Errors from log:

2024-01-12 13:39:48 Updating the configuration and installing your custom providers, if any. Please wait.
2024-01-12 13:39:50 2024-01-12 12:39:49,921 WARN [org.keycloak.services] (build-24) KC-SERVICES0047: magic-link (io.phasetwo.keycloak.magic.resources.MagicLinkResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2024-01-12 13:39:50 2024-01-12 12:39:50,015 WARN [org.keycloak.services] (build-24) KC-SERVICES0047: ext-magic-form (io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2024-01-12 13:39:50 2024-01-12 12:39:50,015 WARN [org.keycloak.services] (build-24) KC-SERVICES0047: ext-email-otp (io.phasetwo.keycloak.magic.auth.EmailOtpAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2024-01-12 13:39:50 2024-01-12 12:39:50,180 WARN [org.keycloak.services] (build-24) KC-SERVICES0047: ext-magic-link (io.phasetwo.keycloak.magic.auth.token.MagicLinkActionTokenHandlerFactory) is implementing the internal SPI actionTokenHandler. This SPI is internal and may change without notice
2024-01-12 13:39:54 2024-01-12 12:39:54,512 INFO [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 5439ms
2024-01-12 13:39:56 2024-01-12 12:39:55,352 INFO [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: Base URL: , Hostname: localhost, Strict HTTPS: false, Path: , Strict BackChannel: false, Admin URL: , Admin: , Port: -1, Proxied: false
2024-01-12 13:39:56 2024-01-12 12:39:56,278 WARN [io.quarkus.agroal.runtime.DataSources] (main) Datasource enables XA but transaction recovery is not enabled. Please enable transaction recovery by setting quarkus.transaction-manager.enable-recovery=true, otherwise data may be lost if the application is terminated abruptly
2024-01-12 13:39:56 2024-01-12 12:39:56,581 WARN [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2024-01-12 13:39:56 2024-01-12 12:39:56,606 WARN [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
2024-01-12 13:39:56 2024-01-12 12:39:56,642 INFO [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
2024-01-12 13:39:57 2024-01-12 12:39:57,510 INFO [org.keycloak.broker.provider.AbstractIdentityProviderMapper] (main) Registering class org.keycloak.broker.provider.mappersync.ConfigSyncEventListener
2024-01-12 13:39:57 2024-01-12 12:39:57,527 INFO [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: node_97155, Site name: null
2024-01-12 13:40:02 2024-01-12 12:40:02,811 INFO [io.quarkus] (main) Keycloak 23.0.4 on JVM (powered by Quarkus 3.2.9.Final) started in 8.243s. Listening on: http://0.0.0.0:8080
2024-01-12 13:40:02 2024-01-12 12:40:02,811 INFO [io.quarkus] (main) Profile dev activated.
2024-01-12 13:40:02 2024-01-12 12:40:02,811 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, logging-gelf, micrometer, narayana-jta, reactive-routes, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, smallrye-health, vertx]
2024-01-12 13:40:02 2024-01-12 12:40:02,813 WARN [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.
2024-01-12 13:42:30 2024-01-12 12:42:30,554 WARN [org.keycloak.events] (executor-thread-6) type=LOGIN_ERROR, realmId=17bdf217-47ca-4f37-985b-82cd81bccf3a, clientId=aspnetcoretest, userId=16954a2b-3064-4e17-87ce-09a763e30daf, ipAddress=172.17.0.1, error=invalid_user_credentials, auth_method=openid-connect, auth_type=code, redirect_uri=https://localhost:5556/signin-oidc, code_id=1072bfef-e2f6-4424-aca1-0cc4aedbee01, username=[email protected]
2024-01-12 13:43:09 2024-01-12 12:43:09,114 WARN [org.keycloak.services.managers.AuthenticationManager] (executor-thread-2) Some clients have been not been logged out for user [email protected] in master realm: aspnetcoretest
2024-01-12 14:17:35 2024-01-12 13:17:35,214 INFO [io.phasetwo.keycloak.magic.MagicLink] (executor-thread-23) Attempting MagicLinkAuthenticator for [email protected], aspnetcoretest, https://localhost:5556/signin-oidc
2024-01-12 14:17:35 2024-01-12 13:17:35,215 INFO [io.phasetwo.keycloak.magic.MagicLink] (executor-thread-23) MagicLinkAuthenticator extra vars openid profile CfDJ8OH3kXTpwkZIn5AIdnE6E8w01cMJltnjli0g4_oduDloc2HdNMKbr-6B01Pae0tJWlwt_DA6puv03EbrmFElLCwCaI4SVwJ4laYHIaNIEjjMgpwTN_28gqxwsvZ6lMhmkDaZTOXWMtX37Aw9depJ0oV8gYULkhPgJaswaYA480pBjdFcwrmcF_L4ZU7R7_BG72rqTq-fKDPXjalXG6QnSjAvZJAkAcm8qH94Sud4ntVu_iHg7Jdr6QOjFbMUIbWYVx_TKul8nQ90J44dKmOLf9g9_caR6QDiOTQZrxcQgEVWsPy8J6DI3EzXT4DMK2xU6VPg9O-PyrCfYLjYPyfiIanJYRn747PyLaToYNdBBNynYFUnDosQcRluu-BDJ_BaIg 638406622489457010.ZDFjZWU0MTItYWEzNi00NWI4LWJlZTAtMWQ2YTMyZWMzOTFhYWNhMzk5NTYtYzFmZi00Mzg5LWE4MjctMWU1Y2Q1NjQxMzI0 true
2024-01-12 14:17:35 2024-01-12 13:17:35,216 WARN [org.keycloak.services] (executor-thread-23) KC-SERVICES0013: Failed authentication: java.lang.IllegalStateException: Magic links not allowed for master realm
2024-01-12 14:17:35 at io.phasetwo.keycloak.magic.MagicLink.linkFromActionToken(MagicLink.java:193)
2024-01-12 14:17:35 at io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticator.action(MagicLinkAuthenticator.java:109)
2024-01-12 14:17:35 at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:154)
2024-01-12 14:17:35 at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:988)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:362)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:333)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:325)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:390)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_32b8e198ac3110abd1d5774e83a4cf87858129f4.invoke(Unknown Source)
2024-01-12 14:17:35 at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
2024-01-12 14:17:35 at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
2024-01-12 14:17:35 at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
2024-01-12 14:17:35 at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
2024-01-12 14:17:35 at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
2024-01-12 14:17:35 at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
2024-01-12 14:17:35 at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
2024-01-12 14:17:35 at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
2024-01-12 14:17:35 at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2024-01-12 14:17:35 at java.base/java.lang.Thread.run(Thread.java:840)
2024-01-12 14:17:35
2024-01-12 14:17:35 2024-01-12 13:17:35,216 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-23) Uncaught server error: java.lang.IllegalStateException: Attempted to define event error without first setting the event type
2024-01-12 14:17:35 at org.keycloak.events.EventBuilder.error(EventBuilder.java:226)
2024-01-12 14:17:35 at org.keycloak.authentication.AuthenticationProcessor.handleBrowserException(AuthenticationProcessor.java:833)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:370)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:333)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:325)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:390)
2024-01-12 14:17:35 at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_32b8e198ac3110abd1d5774e83a4cf87858129f4.invoke(Unknown Source)
2024-01-12 14:17:35 at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
2024-01-12 14:17:35 at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
2024-01-12 14:17:35 at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
2024-01-12 14:17:35 at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
2024-01-12 14:17:35 at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
2024-01-12 14:17:35 at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
2024-01-12 14:17:35 at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
2024-01-12 14:17:35 at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
2024-01-12 14:17:35 at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2024-01-12 14:17:35 at java.base/java.lang.Thread.run(Thread.java:840)
2024-01-12 14:17:35
2024-01-12 14:18:03 2024-01-12 13:18:03,098 INFO [io.phasetwo.keycloak.magic.MagicLink] (executor-thread-27) Attempting MagicLinkAuthenticator for [email protected], aspnetcoretest, https://localhost:5556/signin-oidc
2024-01-12 14:18:03 2024-01-12 13:18:03,099 INFO [io.phasetwo.keycloak.magic.MagicLink] (executor-thread-27) MagicLinkAuthenticator extra vars openid profile CfDJ8OH3kXTpwkZIn5AIdnE6E8yv7MBKafT-oaDs59x1i3OoKV2kEbypWiuSreyNCVEWApLNfvmP88k43BOhonZjTgEgvdzfjeRxRqTz7XGmPuhoiqm8faWN1DOlGVE6z6G0q0yG5Jj5CBD7Y-4e41rFSd-nlMXwNJzgNR9BP-YbWU0l9WCLr2zXXbskxMY-fAp-6_9qY74zWDZv8--so5TtU8GcUCZIm1f8EkyR75Ih3X0ejvsnlJqrWlWieRqGrwhgd2WpXPAckjbElGlBo_XX3-byeKEokYYU-IAnoxgX5RrVNuq5BkPMEkuvdmpxiGDbYcBBR53KUp1cVaqfSBGWQHp4_PA1qvJpVHUTaQ_NtMh7mZ4Vt_rom4ZMf6ZEucYwBiPGTx42fwTKlXvtJJBIl3Q 638406622767577075.MGRmYjIzZWEtZDAzOC00MzM5LTk2NjMtYTkyMTQ2MDNmYTY5NDM4YTcwNDctZDM1Yi00NDAwLTg1N2EtZTBhODRmOTc5Mjlh false
2024-01-12 14:18:03 2024-01-12 13:18:03,099 WARN [org.keycloak.services] (executor-thread-27) KC-SERVICES0013: Failed authentication: java.lang.IllegalStateException: Magic links not allowed for master realm
2024-01-12 14:18:03 at io.phasetwo.keycloak.magic.MagicLink.linkFromActionToken(MagicLink.java:193)
2024-01-12 14:18:03 at io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticator.action(MagicLinkAuthenticator.java:109)
2024-01-12 14:18:03 at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:154)
2024-01-12 14:18:03 at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:988)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:362)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:333)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:325)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:390)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_32b8e198ac3110abd1d5774e83a4cf87858129f4.invoke(Unknown Source)
2024-01-12 14:18:03 at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
2024-01-12 14:18:03 at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
2024-01-12 14:18:03 at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
2024-01-12 14:18:03 at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
2024-01-12 14:18:03 at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
2024-01-12 14:18:03 at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
2024-01-12 14:18:03 at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
2024-01-12 14:18:03 at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
2024-01-12 14:18:03 at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2024-01-12 14:18:03 at java.base/java.lang.Thread.run(Thread.java:840)
2024-01-12 14:18:03
2024-01-12 14:18:03 2024-01-12 13:18:03,099 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-27) Uncaught server error: java.lang.IllegalStateException: Attempted to define event error without first setting the event type
2024-01-12 14:18:03 at org.keycloak.events.EventBuilder.error(EventBuilder.java:226)
2024-01-12 14:18:03 at org.keycloak.authentication.AuthenticationProcessor.handleBrowserException(AuthenticationProcessor.java:833)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:370)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:333)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:325)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:390)
2024-01-12 14:18:03 at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_32b8e198ac3110abd1d5774e83a4cf87858129f4.invoke(Unknown Source)
2024-01-12 14:18:03 at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
2024-01-12 14:18:03 at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
2024-01-12 14:18:03 at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
2024-01-12 14:18:03 at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
2024-01-12 14:18:03 at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
2024-01-12 14:18:03 at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
2024-01-12 14:18:03 at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
2024-01-12 14:18:03 at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
2024-01-12 14:18:03 at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2024-01-12 14:18:03 at java.base/java.lang.Thread.run(Thread.java:840)
2024-01-12 14:18:03
2024-01-12 14:32:18 2024-01-12 13:32:18,691 INFO [io.phasetwo.keycloak.magic.MagicLink] (executor-thread-42) Attempting MagicLinkAuthenticator for [email protected], aspnetcoretest, https://localhost:5556/signin-oidc
2024-01-12 14:32:18 2024-01-12 13:32:18,692 INFO [io.phasetwo.keycloak.magic.MagicLink] (executor-thread-42) MagicLinkAuthenticator extra vars openid profile CfDJ8OH3kXTpwkZIn5AIdnE6E8wVhsbNkGIZMcPXFC82sez0eJ6LnK3ceDfAyaC2o7vdKK22ocBnNZsKSniJ5uRDmMaRmjhoH-gYFfcoD3XIqM4GGMBXuXOwTdmUkXvBeo_c7LYb0jrQBGRLZhBlr7AVsUt79zoaUMxvgCjry7XVIZolm7LaNnxLBTVn37zNCjzoaWd_clc8n3qNepS4pdHV_84pci9WZAu6P8qpk1yNjUXYYguf--2Rt-Nn6X2VEdxC8iHhQ2FrrMtnspg3_nmLnFU_oeGEaN9hQCv7jlKttGSqERzHynqydDfldnbzSflfs8tN02lABnILnwCX8w6syYrkv6LIL9Vl6d1nmtWhspZPlTpnLP_Ey5cPIVh75b99DA 638406631319238928.YTg4NjhhZmMtODE3Zi00OWQ3LTljODktYjEzMTJlYzgwOTVkZmE0ZjA3ODctYWIzMS00OTEzLWIxMjUtYWRiMzFhN2UyNjk2 true
2024-01-12 14:32:18 2024-01-12 13:32:18,692 WARN [org.keycloak.services] (executor-thread-42) KC-SERVICES0013: Failed authentication: java.lang.IllegalStateException: Magic links not allowed for master realm
2024-01-12 14:32:18 at io.phasetwo.keycloak.magic.MagicLink.linkFromActionToken(MagicLink.java:193)
2024-01-12 14:32:18 at io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticator.action(MagicLinkAuthenticator.java:109)
2024-01-12 14:32:18 at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:154)
2024-01-12 14:32:18 at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:988)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:362)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:333)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:325)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:390)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_32b8e198ac3110abd1d5774e83a4cf87858129f4.invoke(Unknown Source)
2024-01-12 14:32:18 at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
2024-01-12 14:32:18 at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
2024-01-12 14:32:18 at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
2024-01-12 14:32:18 at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
2024-01-12 14:32:18 at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
2024-01-12 14:32:18 at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
2024-01-12 14:32:18 at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
2024-01-12 14:32:18 at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
2024-01-12 14:32:18 at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2024-01-12 14:32:18 at java.base/java.lang.Thread.run(Thread.java:840)
2024-01-12 14:32:18
2024-01-12 14:32:18 2024-01-12 13:32:18,692 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-42) Uncaught server error: java.lang.IllegalStateException: Attempted to define event error without first setting the event type
2024-01-12 14:32:18 at org.keycloak.events.EventBuilder.error(EventBuilder.java:226)
2024-01-12 14:32:18 at org.keycloak.authentication.AuthenticationProcessor.handleBrowserException(AuthenticationProcessor.java:833)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:370)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:333)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:325)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:390)
2024-01-12 14:32:18 at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_32b8e198ac3110abd1d5774e83a4cf87858129f4.invoke(Unknown Source)
2024-01-12 14:32:18 at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
2024-01-12 14:32:18 at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
2024-01-12 14:32:18 at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
2024-01-12 14:32:18 at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
2024-01-12 14:32:18 at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
2024-01-12 14:32:18 at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
2024-01-12 14:32:18 at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
2024-01-12 14:32:18 at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
2024-01-12 14:32:18 at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2024-01-12 14:32:18 at java.base/java.lang.Thread.run(Thread.java:840)
2024-01-12 14:32:18

What am I doing wrong?

Customizing email templates

Despite adding the magic-link-email.ftl with necessary changes, the updated template doesn't seem to be picked. What is the right way to get a custom template for this plugin to work effectively? And where should the template files be places?

Use in combination with multiple factors

Hi, I would like to use WebAuthn or TOTP as second factor with the magic links.

Currently if i create a flow like this:
image

The second factor is just skipped instead of working with the default Username Password Form
image

ModuleNotFoundException: org.keycloak.keycloak-admin-client" in Docker container

I tried the following (I'm a Java noob):

I checked out this repo.

Then I ran

docker run -it --rm --name my-maven-project -v "$(pwd)":/usr/src/mymaven -w /usr/src/mymaven maven:3.3-jdk-8 mvn clean install

I created an empty folder where I copied the file keycloak-magic-link-0.2-SNAPSHOT.jar from the target folder into.
Next, I created a docker-compose.yml file inside the same folder.

version: "3"

services:
  keycloaktestdb:
    container_name: keycloaktestdb
    image: postgres:14
    ports:
      - 5434:5432
    environment:
      - POSTGRES_DB=keycloak
      - POSTGRES_USER=keycloak
      - POSTGRES_PASSWORD=password
  idptest:
    image: quay.io/keycloak/keycloak:16.1.1
    container_name: idptest
    depends_on:
      - keycloaktestdb
    ports:
      - 8081:8080
    environment:
      - DB_VENDOR=POSTGRES
      - DB_ADDR=keycloaktestdb
      - DB_DATABASE=keycloak
      - DB_USER=keycloak
      - DB_SCHEMA=public
      - DB_PASSWORD=password
      - KEYCLOAK_USER=admin
      - KEYCLOAK_PASSWORD=admin
    volumes:
        - ./keycloak-magic-link-0.2-SNAPSHOT.jar:/opt/jboss/keycloak/standalone/deployments/keycloak-magic-link-0.2-SNAPSHOT.jar

As you can see, I've mapped the keycloak-magic-link-0.2-SNAPSHOT.jar into the deployments folder.

Next I ran docker compose up -d.

docker logs idptest gave me these errors:

12:30:02,963 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-3) MSC000001: Failed to start service jboss.module.service."deployment.keycloak-magic-link-0.2-SNAPSHOT.jar".main: org.jboss.msc.service.StartException in service jboss.module.service."deployment.keycloak-magic-link-0.2-SNAPSHOT.jar".main: WFLYSRV0179: Failed to load module: deployment.keycloak-magic-link-0.2-SNAPSHOT.jar
	at [email protected]//org.jboss.as.server.moduleservice.ModuleLoadService.start(ModuleLoadService.java:116)
	at [email protected]//org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
	at [email protected]//org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
	at [email protected]//org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
	at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
	at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
	at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.jboss.modules.ModuleNotFoundException: org.keycloak.keycloak-admin-client
	at org.jboss.modules.Module.addPaths(Module.java:1259)
	at org.jboss.modules.Module.link(Module.java:1615)
	at org.jboss.modules.Module.relinkIfNecessary(Module.java:1643)
	at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:303)
	at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:287)
	at [email protected]//org.jboss.as.server.moduleservice.ModuleLoadService.start(ModuleLoadService.java:93)
	... 8 more

and

12:30:22,399 ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "keycloak-magic-link-0.2-SNAPSHOT.jar")]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.module.service.\"deployment.keycloak-magic-link-0.2-SNAPSHOT.jar\".main" => "WFLYSRV0179: Failed to load module: deployment.keycloak-magic-link-0.2-SNAPSHOT.jar
    Caused by: org.jboss.modules.ModuleNotFoundException: org.keycloak.keycloak-admin-client"}}
12:30:22,489 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 33) WFLYSRV0010: Deployed "keycloak-magic-link-0.2-SNAPSHOT.jar" (runtime-name : "keycloak-magic-link-0.2-SNAPSHOT.jar")
12:30:22,490 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 45) WFLYSRV0010: Deployed "keycloak-server.war" (runtime-name : "keycloak-server.war")
12:30:22,491 INFO  [org.jboss.as.controller] (Controller Boot Thread) WFLYCTL0183: Service status report
WFLYCTL0186:   Services which failed to start:      service jboss.module.service."deployment.keycloak-magic-link-0.2-SNAPSHOT.jar".main: WFLYSRV0179: Failed to load module: deployment.keycloak-magic-link-0.2-SNAPSHOT.jar

12:30:22,570 INFO  [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0212: Resuming server
12:30:22,575 ERROR [org.jboss.as] (Controller Boot Thread) WFLYSRV0026: Keycloak 16.1.1 (WildFly Core 18.0.4.Final) started (with errors) in 23445ms - Started 686 of 989 services (2 services failed or missing dependencies, 698 services are lazy, passive or on-demand)
12:30:22,577 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management
12:30:22,578 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990

Did I do something wrong?

Magic link doesn't support PKCE

I was planning to the magic link extension with a standard Authorization Flow incl. PKCE (the use case is a mobile app logging in a user via email to access an API). In general everything works fine, but at the end I realised that it doesn't seem to work with PKCE, i.e., the code_verifier is ignored when sending it.

My assumption was that the magic-link extension doesn't really get involved in PKCE handling, but when I use something else (e.g., standard username+password) instead of the magic link it works fine.

Is this not possible when using the magic link or is it just a limitation/bug in the magic link extension... or am I doing something wrong?

Example request to initiate the flow:
https://my-keycloak/realms/test/protocol/openid-connect/auth?client_id=my-client&response_type=code&scope=email openid&redirect_uri=https://my-redirect-url/&state=my-random-state&nonce=my-random-nonce&code_challenge=Uz9stxVbetoK4mdkE8LLzl7UyMIPra5DyIputr9FWCA&code_challenge_method=S256&[email protected]

When clicking the magic link in the email https://my-keycloak/realms/test/login-actions/action-token?key=eyJhbGciOiJIUzI1NiIsIn....&client_id=my-client
I'm getting a redirect that only contains code and session_state, but not state or nonce.

Requesting the access_token using the code from the magic-link response with an INVALID code_verifier still gives me a valid access_token. Keycloak doesn't seem to expect a code_verifier and silently ignores it.

`mvn clean install` fails on latest main commit

Sorry in advance if this is an obvious issue on my side... I know nothing about Java.

I'm trying to build using homebrew's latest maven package to build the plugin.

On the (currently) penultimate commit f532f15 mvn clean install succeeds.

... but on current latest master commit aeae846, mvn clean install fails with the following:

[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /Volumes/dev/keycloak-magic-link/src/main/java/io/phasetwo/keycloak/magic/auth/MagicLinkAuthenticator.java:[57,5] cannot find symbol
  symbol:   class MagicLinkActionToken
  location: class io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticator
[ERROR] /Volumes/dev/keycloak-magic-link/src/main/java/io/phasetwo/keycloak/magic/auth/MagicLinkAuthenticator.java:[65,12] cannot find symbol
  symbol:   method setAuthNote(java.lang.String,java.lang.String)
  location: variable context of type org.keycloak.authentication.AuthenticationFlowContext
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.547 s
[INFO] Finished at: 2022-08-26T17:26:42+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project keycloak-magic-link: Compilation failure: Compilation failure:
[ERROR] /Volumes/dev/keycloak-magic-link/src/main/java/io/phasetwo/keycloak/magic/auth/MagicLinkAuthenticator.java:[57,5] cannot find symbol
[ERROR]   symbol:   class MagicLinkActionToken
[ERROR]   location: class io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticator
[ERROR] /Volumes/dev/keycloak-magic-link/src/main/java/io/phasetwo/keycloak/magic/auth/MagicLinkAuthenticator.java:[65,12] cannot find symbol
[ERROR]   symbol:   method setAuthNote(java.lang.String,java.lang.String)
[ERROR]   location: variable context of type org.keycloak.authentication.AuthenticationFlowContext
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

How to use with Vue app

I followed the guide, installed the extension on Ketcloak v18 Quarkus and then, using Curl, requested the generation of a magic link that has allowed me to access the account-console client with the new user.

Now I'm trying to use a magic link to access a Vuejs application, but I'm not able to authenticate a new user.

In Keycloak I created and configured a new client for the Vue application and requested a magik link with parameters like these:

{
    "email":"[email protected]",
    "client_id":"test.app",
    "redirect_uri":"http://localhost:8099/purchase",
    "expiration_seconds":3600,
    "force_create":true,
    "update_profile":false,
    "send_email":false
}

The response contains a magic link like this:

{
    "user_id": "50000949-d032-4e04-bf98-5a1ed24a3862",
    "link": "http://0.0.0.0:8900/realms/test/login-actions/action-token?key=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5NDM3YTU5YS03ZWEzLTRjMjktODM5ZS02YjM1YTIxN2ZmNTEifQ.eyJleHAiOjE2NTY0MTA3MDgsImlhdCI6MTY1NjQwNzEwOCwianRpIjoiNzhlOTM3MGEtY2VmYi00YWRlLWE1N2YtMzg5NzNjNjA5ZmJmIiwiaXNzIjoiaHR0cDovLzAuMC4wLjA6ODkwMC9yZWFsbXMvY29tbWVyY2lvIiwiYXVkIjoiaHR0cDovLzAuMC4wLjA6ODkwMC9yZWFsbXMvY29tbWVyY2lvIiwic3ViIjoiNTAwMDA5NDktZDAzMi00ZTA0LWJmOTgtNWExZWQyNGEzODYyIiwidHlwIjoiZXh0LW1hZ2ljLWxpbmsiLCJhenAiOiJ0ZXN0LmVkZWxpdmVyeS5hcHAiLCJub25jZSI6Ijc4ZTkzNzBhLWNlZmItNGFkZS1hNTdmLTM4OTczYzYwOWZiZiIsInJkdSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA5OS9wdXJjaGFzZSJ9.cFFQW5m5IsuD_uVFZKiH88WR4lTe55AnbixxTdzi7hA&client_id=test.app",
    "sent": false
}

In the Vue application I use the Javascript adapter to authenticate the user, first I create a new Keycloak instance and then call the init method. After clicking the magic link and being redirected to the correct page, the Javascript adapter fails to authenticate and does not contain the token.

The to parameter of the route contains these values:

{
   "query":{
     "session_state":"49cc8580-81a0-433c-9bfd-4af8de180a3e",
      "code":"4daa9305-08c0-4712-8d37-5fa6e80b59b9.49cc8580-81a0-433c-9bfd-4af8de180a3e.d7e9ea85-90ff-475c-aa84-fa8cded4ebe8"
  }
}

Could you help me understand how to use magic link with Vue application?

Does the Keycloak client or javascript library need any special configuration?

Thanks

Issuer/audience do not behave the same between production and dev

If i start keycloak with the start-dev parameter and generate a magic link the link's jwt will have issuer and audience equal to the request's host header.
Example :

await axios.post(`${process.env.KEYCLOAK_URL}/realms/${this.realm}/magic-link`, {
      email,
      client_id: `meteorjs`,
      redirect_uri,
      expiration_seconds: verificationLinkTimeout,
      remember_me: true,
    }, {
      headers: {
        Accept: `application/json`,
        'Content-Type': `application/json`,
        Authorization: `Bearer ${this.token}`,
        host: `test.com`,
      },
    });

The link is :

https://auth.localhost:8443/realms/testfordev/login-actions/action-token?key=eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjY2QxZGY3Ny02NTkyLTRhNzEtYjFhOC03MGQyYjFhNjE1MGMifQ.eyJleHAiOjE3MDk3MzA2OTAsImlhdCI6MTcwOTczMDM5MCwianRpIjoiN2M5NWZiMTQtMTFkMi00ZjQ1LWJlNmEtZjM3YTNmOWNiZTUxIiwiaXNzIjoiaHR0cHM6Ly90ZXN0LmNvbS9yZWFsbXMvdGVzdGZvcmRldiIsImF1ZCI6Imh0dHBzOi8vdGVzdC5jb20vcmVhbG1zL3Rlc3Rmb3JkZXYiLCJzdWIiOiI5ZjMzNjZkZi1iOTNlLTQxYmItODhjZS03MGRhODczNzIyNjEiLCJ0eXAiOiJleHQtbWFnaWMtbGluayIsImF6cCI6Im1ldGVvcmpzIiwibm9uY2UiOiI3Yzk1ZmIxNC0xMWQyLTRmNDUtYmU2YS1mMzdhM2Y5Y2JlNTEiLCJyZHUiOiJodHRwczovL3Rlc3Rmb3JkZXYubG9jYWxob3N0LyIsInJtZSI6dHJ1ZSwicnUiOnRydWV9.b7uYYz8LJ60FO-AkF3jqWj87VNLiVML5m0mjZjEy7dsNKdGhxFLyc9p5o8N3Tvgtu3gExrtfW3PVUkkqY8vJeg&client_id=meteorjs

If i derialize the key, it is :

{
  "exp": 1709730690,
  "iat": 1709730390,
  "jti": "7c95fb14-11d2-4f45-be6a-f37a3f9cbe51",
  "iss": "https://test.com/realms/testfordev",
  "aud": "https://test.com/realms/testfordev",
  "sub": "9f3366df-b93e-41bb-88ce-70da87372261",
  "typ": "ext-magic-link",
  "azp": "meteorjs",
  "nonce": "7c95fb14-11d2-4f45-be6a-f37a3f9cbe51",
  "rdu": "https://testfordev.localhost/",
  "rme": true,
  "ru": true
}

Note that the issuer and audience have the same value as the host header in the request.

Now if i make the same request with "start" and "--hostname-url=https://auth.localhost:8443". I get :

https://auth.localhost:8443/realms/testinprod/login-actions/action-token?key=eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5OTJlZDk5ZC01YTZhLTQ4MDUtYjg1Ni1jMGFmZTg5ZmU2OTYifQ.eyJleHAiOjE3MDk3MzEwODIsImlhdCI6MTcwOTczMDc4MiwianRpIjoiYTNmZDg4YzAtYTc4MC00NGRjLTgyZDYtNmI4ODVhZmM4Yjg3IiwiaXNzIjoiaHR0cHM6Ly9hdXRoLmxvY2FsaG9zdDo4NDQzL3JlYWxtcy90ZXN0aW5wcm9kIiwiYXVkIjoiaHR0cHM6Ly9hdXRoLmxvY2FsaG9zdDo4NDQzL3JlYWxtcy90ZXN0aW5wcm9kIiwic3ViIjoiMjU1ZGY0OWUtYzc3OC00NWNlLWJlMzctOTJiZDliZDA3N2EzIiwidHlwIjoiZXh0LW1hZ2ljLWxpbmsiLCJhenAiOiJtZXRlb3JqcyIsIm5vbmNlIjoiYTNmZDg4YzAtYTc4MC00NGRjLTgyZDYtNmI4ODVhZmM4Yjg3IiwicmR1IjoiaHR0cHM6Ly90ZXN0aW5wcm9kLmxvY2FsaG9zdC8iLCJybWUiOnRydWUsInJ1Ijp0cnVlfQ.7EEe9svgWSMDqbGqgDv2nOzoco76l_8V6Sbylb6259DxaDKGjTCsMAKT01jvCeoBn-DswyNYHnjay9b1MKRnRA&client_id=meteorjs

Derialize the key and you can see that the issuer and audience have been overwritten by ""--hostname-url":

{
  "exp": 1709731082,
  "iat": 1709730782,
  "jti": "a3fd88c0-a780-44dc-82d6-6b885afc8b87",
  "iss": "https://auth.localhost:8443/realms/testinprod",
  "aud": "https://auth.localhost:8443/realms/testinprod",
  "sub": "255df49e-c778-45ce-be37-92bd9bd077a3",
  "typ": "ext-magic-link",
  "azp": "meteorjs",
  "nonce": "a3fd88c0-a780-44dc-82d6-6b885afc8b87",
  "rdu": "https://testinprod.localhost/",
  "rme": true,
  "ru": true
}

The link also produces an invalid issuer error : "Expected issuer https://testinprod.localhost/realms/testinprod" when clicked.

See 6fe08f9 for a fix.

@xgp please don't hesitate to tell me if you need more details.

Apache Server Authentication and Authorization

I would like to try the plugin for authentication of old websites running on Apache.

For this purpose there exists an apache module called mod_auth_openidc.so which is configured with a client secret.

So, it uses client credential instead of authentication code flow. When clicking on the magic link, a session is created in keycloak, however upon redirect there's following error:

Error:

OpenID Connect Provider error: Error in handling response type.

I'm wondering if the action token has to be created differently for this type of flow or whether the problem lies in the configuration of the Apache module?

Really appreciate you're help!

NullPointerException in MagicLinkAuthenticator if forceCreate is false

When a login is attempted but no such user exists and forceCreate is set to false, the plugin raises a NullPointerException here:

https://github.com/p2-inc/keycloak-magic-link/blob/9821b1e91806b0fe83fa5a4f71225d051d6fecb6/src/main/java/io/phasetwo/keycloak/magic/auth/MagicLinkAuthenticator.java#L85C67-L85C67

Keycloak then proceeds to return a 500 error response due to the following error (but I am not sure if this is caused by the plugin):

Uncaught server error: java.lang.IllegalStateException: Attempted to define event error without first setting the event type

Auto email verification with email OTP

First of all, thanks for building and open-sourcing this great extension.

I noticed that, when using Magic Links, the user's email is automatically marked as verified when they click the link. I believe this code is responsible.

Otherwise, when using Email OTP, nothing is done concerning email verification when a user uses the code to log in.

I am wondering if that is a design choice. Or maybe a technical limitation.

To my understanding, both methods, Magic Link or Email OTP, can ensure that the user has access to their email account, and that their email address should be marked as verified on Keycloak.

Can you provide details about this? Thanks

Simply copy the jar in the provider in the providers folder of quay.io/keycloak/keycloak:21.1.X image leads to org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] ERROR: jakarta.ws.rs.core.UriInfo

Hello and thanks for this amazing provider.

  • I tried it with your standalone image:
    works but your standalone image is unable to import a previously exported realm.

  • I went back to my "vanilla" quay.io/keycloak/keycloak:21.1.X image:
    I see the providers getting loaded,
    WARN [org.keycloak.services] (build-37) KC-SERVICES0047: ext-magic-form... WARN [org.keycloak.services] (build-37) KC-SERVICES0047: ext-email-otp... WARN [org.keycloak.services] (build-37) KC-SERVICES0047: ext-magic-link...
    But keycloak fails to start with ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: jakarta/ws/rs/core/UriInfo. Simply removing the jars from the providers folder made keycloak run again.

  • I then tried a bitnami image and it worked.

I wonder why it doesn't work with the vanilla image.
Could you give me any insight?

Many thanks, have a nice day

java.lang.NoSuchMethodError thrown by MagicLinkAuthenticator.java action() method

Hi,

After initial setup hiccups, I was able to setup this provider with keycloak and got the login screen with the username/email field to appear. I followed this

But when I submit the form in the UI, I get the following exception in the keycloak server logs:
2023-03-09 13:16:06,711 INFO [io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticator] (executor-thread-4) MagicLinkAuthenticator.action 2023-03-09 13:16:06,721 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-4) Uncaught server error: java.lang.NoSuchMethodError: org.keycloak.authentication.AuthenticationFlowContext.getHttpRequest()Lorg/keycloak/http/HttpRequest; at io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticator.action(MagicLinkAuthenticator.java:74) at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:155) at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:977) at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:311) at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:282) at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:274) at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:339) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170) at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130) at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660) at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524) at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474) at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364) at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476) at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434) at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192) at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141) at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.j

This is my setup:

  • keycloak: 20.0.3
  • keycloak-magic-link: d767092

This is what my Authentication flow looks like:
Screenshot 2023-03-09 at 1 58 14 PM

This is what Magic Link Config looks like:
Screenshot 2023-03-09 at 1 59 53 PM

Am I missing something in the config ?

Could not resolve dependencies for project io.phasetwo.keycloak:keycloak-magic-link:jar:0.1-SNAPSHOT: Could not find artifact org.keycloak:keycloak-testsuite-utils:jar:17.0.1 in central (https://repo.maven.apache.org/maven2)

Hello,

I get this error when trying to compile this project :

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.758 s
[INFO] Finished at: 2022-05-12T21:42:20+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project keycloak-magic-link: Could not resolve dependencies for project io.phasetwo.keycloak:keycloak-magic-link:jar:0.1-SNAPSHOT: Could not find artifact org.keycloak:keycloak-testsuite-utils:jar:17.0.1 in central (https://repo.maven.apache.org/maven2) -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

Any idea ?

Thanks in advance

Magic Link + NextAuth with Keycloak as a Provider - nonce mismatch

Hello, first, thanks for the extensions for orgs and magic links. Great stuff.

I'm using NextAuth with Keycloak Provider. I'm also using the p2 containers, with the 0.13 extension installed for keycloak-magic-link.

When I login with user/name password, the oauth callbacks all work correctly and the user can login correctly.

However, when using the magic link flow, the OAuthCallback error is received once the magic link is clicked in the inbox.

Upon clicking signin with the keycloak provider, I see NextAuth creating the authorization url.

State

[next-auth][debug][CREATE_STATE] { value: 'x95OOMOeUbC3dSosVPafp2nzaq8ft2FJvieHMTjrlYA', maxAge: 900 }

Nonce

[next-auth][debug][CREATE_NONCE] { value: '8uMO9nPU9OSEaACq0RvrA5W9nelqNyX06U3I4uP9Qvk', maxAge: 900 }

Generated Authorization Url

[next-auth][debug][GET_AUTHORIZATION_URL] {
  url: 'http://localhost:8080/realms/myrealm/protocol/openid-connect/auth?client_id=nextjs-frontend&scope=openid%20email%20profile&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fapi%2Fauth%2Fcallback%2Fkeycloak&state=x95OOMOeUbC3dSosVPafp2nzaq8ft2FJvieHMTjrlYA&code_challenge=ZUP5pKRC5GHjjfQsxGj3D33xooUbyxtiFZQ8DXrHCZs&code_challenge_method=S256&nonce=8uMO9nPU9OSEaACq0RvrA5W9nelqNyX06U3I4uP9Qvk'}

The generated nonce from NextAuth is passed as a parameter to openid-connect/auth endpoint.

Upon clicking the magic link, I see the following OAuthCallback error:

[next-auth][error][OAUTH_CALLBACK_ERROR]
https://next-auth.js.org/errors#oauth_callback_error nonce mismatch, expected 8uMO9nPU9OSEaACq0RvrA5W9nelqNyX06U3I4uP9Qvk, got: 0f179f93-dd7a-4b63-8cc2-a79c3248317e {
  error: RPError: nonce mismatch, expected 8uMO9nPU9OSEaACq0RvrA5W9nelqNyX06U3I4uP9Qvk, got: 0f179f93-dd7a-4b63-8cc2-a79c3248317e
...
  providerId: 'keycloak',
  message: 'nonce mismatch, expected 8uMO9nPU9OSEaACq0RvrA5W9nelqNyX06U3I4uP9Qvk, got: 0f179f93-dd7a-4b63-8cc2-a79c3248317e'
}

Any ideas @xgp ?

Authentication is skipped if UsernameForm is added before Magic Link

When adding a UsernameForm before the Magic Link authenticator no magic link is sent and authentication succeeds right away.

This is a simple flow to reproduce the issue:

image

Keycloak version 21.1.1 with magic link 0.11.

The reason seems to be that MagicLinkAuthenticator checks for context.getUser() != null and just returns context.success() if it finds a user in the authentication context.

Master realm

Why magic link isn't available in master realm by default?

I don't understand what's the risk here, or is it just to prevent things in Phase Two cloud offering and I am safe to edit it on my own and enable it in my own implementation?

Magic Link 'remember me' don't work

I just noticed that remember me does NOT work with magic links.

I use magic link authentication for a special client
image

Remember me is enabled
image

When I close the Chrome browser and open it again, a new login is required.

The remember me feature also does not work with intentity providers like google.
This is a known missing feature.
The feature seems to be super simple to customize via custom code.
https://keycloak.discourse.group/t/override-keycloak-class/17192/3
Maybe it can be implemented for the magic link feature as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.