---
id: eudi-passwordless-login-flow
title: Passwordless Login with EUDI Wallets
description: See how to enable passwordless authentication using the EUDI Wallet, improving security and user experience with Verifiable Credentials (VC).
hide_title: false
sidebar_label: Passwordless Login
keywords: [passwordless login, EUDI Wallet, authentication, verifiable credentials, Organisation Wallet, European Business Wallet, OpenID Connect, FIDO2, identity verification]
slug: /eudi-passwordless-login-flow/
---

> **Build this with an AI coding agent.** Install the iGrant.io Agent Skills, then ask your agent to build the integration:
>
> ```bash
> npx skills add L3-iGrant/skills
> ```

<head>
  <title>Implement Passwordless Login with the EUDI Wallet | iGrant.io DevDocs</title>
  <meta name="description" content="See how to enable passwordless authentication using the EUDI Wallet, improving security and user experience with Verifiable Credentials (VC)." />
</head>

import YouTubeEmbed from '@site/src/components/YouTubeEmbed';

## Overview

By enabling the OpenID Connect extension in the iGrant.io Organisation Wallet Suite and configuring any OpenID Connect-compatible Identity and Access Management (IAM) system as a relying party (RP), organisations can allow users to log in without a password using their digital wallet credentials.

This guide consists of two parts:
1. **Enable and configure the OpenID Connect extension** in your iGrant.io Organisation Wallet Suite.
2. **Configure your IAM** to use iGrant.io as an OpenID provider with step-by-step guides.

![](./images/eo-ow-passwordless-diagram.png)

## Pre-requisites

Before implementing the passwordless login flow with EUDI Wallets, ensure you have:

- An iGrant.io Organisation Wallet Suite with administrator access
- EUDI Wallet available for testing the authentication flow
- A Presentation Definition ID (create one [here](/docs/openID4vc-send-verify-credentials/))
- A running IAM instance that supports OpenID Connect (e.g. Keycloak 15+, Auth0, Ping Identity, etc.)

## Part 1: Configure the OpenID Connect Extension

### Step 1: Get the API Key (Organisation Admin)

To obtain your API key, please contact [support@igrant.io](mailto:support@igrant.io?subject=Request%20API%20Key). Once you have received your API key, enter it in the field below and click the **Set API Key** button to save it for future use.

import { ApiKeyManager } from '@site/src/components/ApiKeyManager';

<ApiKeyManager />

### Step 2: Enable the OpenID Connect Extension

To enable the OpenID Connect extension, run the code block below using the **Run** button. This will enable the extension and provide you with the OpenID Connect metadata discovery URL (`/.well-known/openid-configuration`), copy it for IAM configuration (Step 4).

import Enable from '@site/src/components/PasswordlessLogin/Enable';

<Enable
  requestBodyOptions={[
    {
      requestBodyJson: {
        extensionId: "oidc",
        enabled: true,
      },
    }
  ]}
/>

Alternatively you can do this step manually by copying the code block and using it in the body of the API request available [here](/docs/extensions-api/set-extension-enabled-state) (select https://demo-api.igrant.io from the Base URL dropdown). Copy the OpenID Connect metadata discovery URL (`/.well-known/openid-configuration`) for IAM configuration (Step 4).

### Step 3: Create an OpenID Client

You will need the Presentation Definition ID you created in the pre-requisites, as well as the following from your IAM:
- Redirect URI
- Allowed origin (based on the redirect URI's domain)

Run the code block below using the **Run** button to create an OpenID Connect client. This will provide you with the Client ID and Client Secret, copy them for IAM configuration (Step 4).

**Note:** If you don't already have the Redirect URI it can be [updated later](/docs/extensions-api/update-oidc-client) and left blank for now, see the IAM-specific section below for instructions on where to find it.

import Client from '@site/src/components/PasswordlessLogin/Client';

<Client
  requestBodyOptions={[
    {
      requestBodyJson: {
        presentationDefinitionId: "string",
        name: "Login with EUDI Wallet",
        transactionDataAction: "Log in to your online bank account",
        redirectURIs: [
          "string"
        ],
        allowedOrigins: [
          "string"
        ],
        identityMatchingAttributes: {
          "https://example.com/vct/drivers-license": "email"
        },
      },
    }
  ]}
/>

:::note
- **`transactionDataAction`**: A free-text value (e.g. `"Log in to your online bank account"`) included in the transaction data sent to the EUDI Wallet when the presentation definition supports it. The wallet may use this to display a custom UI to the user (e.g. a contextual message about what the login is for).
- **`identityMatchingAttributes`**: A map of VCTs (verifiable credential types) to claim paths used as linking values for identity matching. Each key is the VCT of a credential, and the value is the dot-separated path to the claim within that credential to use as the linking value. This is the recommended way to configure identity matching. Example: `{"https://example.com/vct/drivers-license": "email"}` maps the `email` claim from the drivers licence credential for identity matching.
- **`callbackURI`** (optional): An HTTPS endpoint for complex identity matching scenarios. When set, the endpoint receives the credential presentation and returns the `sub` claim. Use this when you need custom logic beyond what `identityMatchingAttributes` can provide. Your callback must return a JSON response with a `sub` field, the subject identifier used to link the user in your IdP.
- **`callbackSecret`** (required when `callbackURI` is set): A secret used to sign the callback payload with HMAC-SHA256. Use this to verify that callback requests genuinely originate from iGrant.io. See [Webhook Security](/docs/openid4vc-webhooks/#webhook-security) for details on how to decode and verify the `X-iGrant-Signature` header.
:::

## Part 2: Configure Your IAM

Organisations can configure iGrant.io as an OpenID provider in any OIDC-compatible IAM. Below are step-by-step guides for Keycloak and Auth0.

### Keycloak Configuration

Follow these steps to configure Keycloak as a relying party.

#### Step 4: Add an Identity Provider (IdP)

1. Log in to your Keycloak admin console.
2. Navigate to **Identity providers** > **Add provider** > **OpenID Connect v1.0**.

![](./images/eo-ow-passwordless-idp-1.png)
_Figure 01: Add Identity Provider_

3. Enter the following details:
   - **Alias**: e.g., `igrant`
   - **Client ID**: (from step 3)
   - **Client Secret**: (from step 3)
   - **Discovery endpoint**: Paste the metadata discovery URL from step 2
   - **Client Authentication**: Set to **Client Secret sent as basic auth**.

![](./images/eo-ow-passwordless-idp-2.png)
_Figure 02: Add OpenID Connect Provider_

If the discovery endpoint cannot be used directly, retrieve individual endpoints (authorisation, token, userinfo, and JWKS) from the metadata URL (Step 2) in the browser and configure them manually.

**Note:** You can find the Redirect URI in the settings, update the client [here](/docs/extensions-api/update-oidc-client) if not already done.

#### Step 5: Create a Custom Authentication Flow in Keycloak

1. Go to **Authentication** > **Flows**.

![](./images/eo-ow-passwordless-authentication-1.png)
_Figure 03: Authentication_

2. Create a new basic flow, e.g., "Login with EUDI Wallet".

![](./images/eo-ow-passwordless-authentication-2.png)
_Figure 04: Add Authentication Flow_

3. Add execution steps required for OpenID Connect-based login.

![](./images/eo-ow-passwordless-authentication-3.png)
_Figure 05: Add Execution Steps_

4. Mark each step as required to enforce proper validation.
5. Save the flow.

Alternatively, add these steps to your current login flow.

**Explanation:**
- **Detect existing broker user**: On login from an external IdP, the authenticator checks for a local Keycloak account that matches the external identity (matched via the identity matching attributes configured on the OIDC client). Only users who already exist can continue.
- **Automatically set existing user**: If a matching local user is found, the authenticator "injects" the user into the authentication context and completes the login (no further confirmation, e.g. password re-entry or email-link is requested).

#### Step 6: Update the Authentication Flow and Sync Mode in Keycloak

1. Navigate to your Identity Provider settings in Keycloak.
2. Set the newly created (or updated) authentication flow for the identity provider (e.g. "Login with EUDI Wallet").
3. Configure the sync mode ("force" is recommended as it will re-apply the identity matching attributes on every login).

![](./images/eo-ow-passwordless-idp-3.png)
_Figure 06: Update the Authentication Flow and Sync Mode in Keycloak_

##### Sample Implementation with React (Keycloak)

A GitHub repository is available that demonstrates how to implement a custom "Sign in with EUDI Wallet" button in a React application integrated with Keycloak IAM:

- **Repository**: [https://github.com/L3-iGrant/passwordless-login-playground](https://github.com/L3-iGrant/passwordless-login-playground)
- **Features**:
  - Complete React frontend with EUDI Wallet login button
  - Integration with Keycloak as the identity provider
  - Step-by-step setup instructions

---

### Auth0 Configuration

Follow these steps to configure Auth0 as a relying party.

#### Step 4: Create an Application in Auth0

1. Log in to your Auth0 dashboard and navigate to **Applications** > **Applications**.

![](./images/eo-ow-passwordless-auth0-application-1.png)
_Figure 07: Applications list_

2. Click **+ Create Application**, give your application a name (e.g. `Auth0 App`), and select the appropriate type (e.g. **Single Page Web Application** for React apps). Click **Create**.

![](./images/eo-ow-passwordless-auth0-application-2.png)
_Figure 08: Create Application_

3. In the application **Settings** tab, note the **Client ID** and **Domain**. Scroll down to **Application URIs** and fill in:
   - **Allowed Callback URLs**: Your application's post-login redirect URL (e.g. `http://localhost:18080/dashboard`)
   - **Allowed Logout URLs**: Your application's logout URL

![](./images/eo-ow-passwordless-auth0-application-3.png)
_Figure 09: Application Basic Information_

![](./images/eo-ow-passwordless-auth0-application-4.png)
_Figure 10: Application URIs_

4. Under **Advanced Settings** > **Grant Types**, ensure **Authorization Code** is enabled.

![](./images/eo-ow-passwordless-auth0-application-5.png)
_Figure 11: Grant Types_

#### Step 5: Create a Custom Social Connection

Auth0 connects to iGrant.io as a **Custom Social Connection** using the OIDC endpoints from Step 2.

1. Navigate to **Authentication** > **Social** and click **+ Create Connection**.
2. Scroll to the bottom and select **Create Custom**.

![](./images/eo-ow-passwordless-auth0-connection-2.png)
_Figure 12: Social Connections – Create Custom_

3. Set the **Purpose** to **Authentication** and click **Next**.

![](./images/eo-ow-passwordless-auth0-connection-3.png)
_Figure 13: New Custom Social Connection – Purpose_

4. Fill in the connection details using the values from Steps 2 and 3:
   - **Name**: e.g. `Passwordless-Login`
   - **Authorization URL**: The authorisation endpoint from the iGrant.io OIDC discovery document
   - **Token URL**: The token endpoint from the iGrant.io OIDC discovery document
   - **Scope**: `openid`
   - **Client ID**: (from step 3)
   - **Client Secret**: (from step 3)

![](./images/eo-ow-passwordless-auth0-connection-4.png)
_Figure 14: Connection configuration – Authorization & Token URLs_

5. In the **Fetch User Profile Script** field, enter a script that calls the iGrant.io UserInfo endpoint to retrieve the user's profile. Replace the URL with your organisation's UserInfo endpoint (found in the OIDC discovery document from Step 2). The following snippet also maps the user profile to Auth0's format:

:::note
The `Authorisation` header must be added with a base64-encoded Client ID and Client Secret (formatted as `client_id:client_secret`).
:::

```javascript
function(accessToken, ctx, cb) {
    const request = require('request');
    const options = {
        url: 'https://<your-org-api>/v3/service/extension/oidc/<organisationId>/<clientId>/userinfo',
        headers: {
            Authorization: `Bearer ${accessToken}`
        },
        json: true
    };

    request.get(options, (err, response, body) => {
        if (err || response.statusCode !== 200) {
            return cb(new Error('Failed to fetch user profile'));
        }

        // Map the user profile to Auth0's format
        const profile = {
            user_id: body.sub, // Unique identifier from your IdP
            username: body.presentation["0"].email,
            nickname: body.presentation["0"].given_name,
            name: body.presentation["0"].given_name + " " + body.presentation["0"].family_name,
            email: body.presentation["0"].email,
        };

        cb(null, profile);
    });
}
```

![](./images/eo-ow-passwordless-auth0-connection-5.png)
_Figure 15: Fetch User Profile Script and Client credentials_

![](./images/eo-ow-passwordless-auth0-connection-6.png)
_Figure 16: Full Fetch User Profile Script_

6. Click **Create** to save the connection.

#### Step 6: Enable the Connection for Your Application

1. Navigate back to your application (**Applications** > **Applications** > your app).
2. Go to the **Connections** tab.
3. Enable the **Passwordless-Login** custom social connection you just created.

![](./images/eo-ow-passwordless-auth0-application-6.png)
_Figure 17: Enable connection for the application_

Once enabled, Auth0 will route authentication requests to iGrant.io and use the UserInfo endpoint to populate the user's profile in Auth0.

**Note:** You can find the Redirect URI for the iGrant.io client in your Auth0 application's **Settings** tab. Update the iGrant.io OIDC client [here](/docs/extensions-api/update-oidc-client) to include it if not already done.

### Try It Yourself

Watch a short demo of the passwordless login flow with the EUDI Wallet:

<YouTubeEmbed
  videoId="WysMxTDcPSc"
  title="Passwordless Login with EUDI Wallets | Secure Digital Identity Login Demo | OpenID Connect"
  description="Watch how passwordless login works with the European Digital Identity Wallet (EUDI Wallet), using the iGrant.io Organisation Wallet Suite and Data Wallet. The demo shows how organisations integrate EUDI Wallet authentication into existing IAM systems via OpenID Connect to enable secure passwordless access."
  uploadDate="2026-07-07"
  duration="PT3M51S"
  thumbnailUrl="https://i.ytimg.com/vi/WysMxTDcPSc/maxresdefault.jpg"
/>