Bring Your Own IDP

Bring Your Own IDP

This feature requires a subscription to Growth Plan

View pricing

# ⁠Overview

Our OIDC extension integrates with your existing identity provider using OpenID Connect for authentication. It enables third-party identity providers to securely pass signed JWTs (OIDC tokens) for verification by Magic. This facilitates user authentication and registration while granting access to web3-capable wallets across 20+ blockchains.

#Compatibility

note

Only available with Dedicated Wallet.

OIDC extension methods are available on the following client-side SDKs:

#What is Open ID Connect?

OpenID Connect 1.0 is an identity layer built on top of the OAuth 2.0 protocol. It allows clients to confirm a user's identity through authentication by an authorization server and obtain fundamental profile details in a standardized, REST-like format.

For more information about this identity protocol, please visit the Open ID docs.

#Configuration

Before getting started using a custom identity provider, you will need to acquire the following values that Magic relies on to connect with those providers.

PropertyType

Required (POST)

Description

IssuerString

Yes

The URL of the token issuer.

audienceString

Yes

The identifier of the audience, often the same as the IdP client ID to which the token is issued.

display_nameString

Yes

A human-readable identifier for the entity.

sandbox_mode

Bool

No (defaults false)

When true, provider does not enforce the expiry claim during ID token validation, which can be useful for testing environments.

Magic Publishable API Key

String

Yes

The publishable API key retrieved from the Magic dashboard.

note

The flow to finding the required information will vary depending on your identity provider. Please refer to the README in one of the various OIDC demos pertaining to your specific identity provider.

With this information, you can configure your application's custom identity provider by calling our API with the Magic secret key sent in the X-Magic-Secret-Key header.

Upon successful configuration in Magic's backend, the API will return a providerId, which is a string of letters and numbers. Please save this, you will need this value each time you provision a wallet for your end user.

#Endpoints

Please call the POST endpoint for initial configuration of your application's custom identity provider with Magic. Subsequent updates can be accomplished by calling the PATCH endpoint.

  • POST Endpoint: https://api.magic.link/v1/api/magic_client/federated_idp

Example POST call

Web
Curl
01const magic_resp = await fetch("https://api.magic.link/v1/api/magic_client/federated_idp", {
02  method: "POST",
03  headers: {
04    "Content-Type": "application/json",
05    "X-Magic-Secret-Key": "<sk_live_xxxxxxx>",
06  },
07  body: JSON.stringify({
08    issuer: "https://auth.examplecorp.com",
09    audience: "Xk8v3hjZP5RfzqWb4JtMn0E2sYpL9A1u",
10    display_name: "example-corp-dev",
11    sandbox_mode: true
12  })
13})
14
15const magic_json = await magic_resp.json()
16const provider_Id = magic_json.data['id']
17
18// Responds 200 OK with new provider on successful create
19{
20  "data": {
21      "audience": "Xk8v3hjZP5RfzqWb4JtMn0E2sYpL9A1u",
22      "discovery_uri": "https://auth.examplecorp.com/.well-known/openid-configuration",
23      "display_name": "example-corp-dev",
24      "id": "3LDeve5f56ouY_tN-jLJlop_hkLI1LLTNG8abaCD42E=",
25      "is_active": true,
26      "issuer": "https://auth.examplecorp.com",
27      "jwks_uri": "https://auth.examplecorp.com/jwks.json",
28      "jwkset": null,
29      "magic_client": null,
30      "magic_client_id": "3LDeve5f56ouY_tN-jLJlop_hkLI1LLTNG8abaCD42E=",
31      "profile": "custom",
32      "sandbox_mode": true,
33      "store_verified_email_enabled": false,
34      "time_created": 1707238543,
35      "time_updated": 1707238543,
36      "type": "jwt"
37  },
38  "error_code": "",
39  "message": "",
40  "status": "ok"
41}

To update, you will need to affix your application's providerId to the PATCH endpoint. Only values passed to the request body will be updated.

  • PATCH Endpoint: https://api.magic.link/v1/api/magic_client/federated_idp/<provider_Id>

Example PATCH call

Web
Curl
01const magic_resp = await fetch("https://api.magic.link/v1/api/magic_client/federated_idp/<provider_Id>", {
02  method: "PATCH",
03  headers: {
04    "Content-Type": "application/json",
05    "X-Magic-Secret-Key": "<sk_live_xxxxxxx>",
06  },
07  body: JSON.stringify({
08    issuer: "https://auth.examplecorp2.com",
09    display_name: "example-corp2-dev",
10    sandbox_mode: false
11  })
12})
13// Only values passed to body will be updated
14
15const magic_json = await magic_resp.json()
16const provider_Id = magic_json.data['id']
17
18// Responds 200 OK with updated provider on successful patch 
19{
20  "data": {
21      "audience": "Xk8v3hjZP5RfzqWb4JtMn0E2sYpL9A1u",
22      "discovery_uri": "https://auth.examplecorp2.com/.well-known/openid-configuration",
23      "display_name": "example-corp2-dev",
24      "id": "3LDeve5f56ouY_tN-jLJlop_hkLI1LLTNG8abaCD42E=",
25      "is_active": true,
26      "issuer": "https://auth.examplecorp2.com",
27      "jwks_uri": "https://auth.examplecorp2.com/jwks.json",
28      "jwkset": null,
29      "magic_client": null,
30      "magic_client_id": "3LDeve5f56ouY_tN-jLJlop_hkLI1LLTNG8abaCD42E=",
31      "profile": "custom",
32      "sandbox_mode": false,
33      "store_verified_email_enabled": false,
34      "time_created": 1707238543,
35      "time_updated": 1707238544,
36      "type": "jwt"
37  },
38  "error_code": "",
39  "message": "",
40  "status": "ok"
41}

#Installation

To use your own identity provider, you must install both magic-sdk and the OIDC extension: @magic-ext/oidc

NPM
Yarn
01npm install magic-sdk @magic-ext/oidc
02

#Initialization

#Import Required Modules

Import the necessary modules into your application. You'll need the magic-sdk, @magic-ext/oidc, and your identity provider's OIDC client library. Here's an example in JavaScript:

Javascript
01import { Magic } from "magic-sdk";
02import { OpenIdExtension } from "@magic-ext/oidc";
03// this is an example of an OIDC client library
04import { useAuth0 } from "@auth0/auth0-react";

#Initialize the Magic SDK

Create an instance of the Magic SDK with your API key. Ensure that you include the OpenIdExtension to enable OIDC functionality:

Javascript
01const magic = new Magic('<your_magic_api_key>', {
02  // exposes the openid module in your magic instance
03  extensions: [new OpenIdExtension()],
04});

#Usage

Now that you've set up a Magic client, you can proceed to authenticate users via your preferred OIDC Client:

Javascript
01// identity providers have different ways to authenticate a user
02// this is an example of an OIDC client library's login methods
03import { useAuth0 } from "@auth0/auth0-react";
04
05const { loginWithRedirect } = useAuth0();
06
07async function loginUser() {
08  await loginWithRedirect();
09};

After authentication, you can obtain the OIDC token from the identity provider. Pass this token, along with the providerId, to the Magic method loginWithOIDC:

Javascript
01// identity providers have varying ways to obtain an OIDC token
02// this is an example of an OIDC client library's token methods
03import { useAuth0 } from "@auth0/auth0-react";
04
05async function getMagicWallet() {
06  const { getIdTokenClaims } = useAuth0();
07
08  const token = await getIdTokenClaims();
09  // resolves a DID token and stores a valid session to browser
10  const didToken = await magic.openid.loginWithOIDC({
11    jwt: token.__raw,
12    providerId: '<your_magic_provider_id>',
13  )};
14};

You can also utilize relevant Magic client SDK methods in the User Module to extend further functionality:

Javascript
01// metadata will only contain issuer and publicAddress
02const metadata = await magic.user.getInfo();
03// DID token default lifespan 15 minutes
04const didToken = await magic.user.getIdToken();
05// returns true if auth user has a valid Magic session
06const boolean = await magic.user.isLoggedIn();

A full example incorporating web3 and Magic OIDC:

Javascript
01import Web3 from 'web3';
02import { Magic } from 'magic-sdk';
03import { OpenIdExtension } from '@magic-ext/oidc';
04
05const magic = new Magic('<your_magic_api_key>', {
06  extensions: [new OpenIdExtension()],
07});
08const DID = await magic.openid.loginWithOIDC({
09  // this oidcToken comes from the identity provider
10  jwt: oidcToken,
11  // this providerId is provided by Magic
12  providerId: myProviderId,
13});
14
15const web3 = new Web3(magic.rpcProvider);
16await web3.eth.getAccounts();

#Errors

The following are OIDC Extension Specific errors.

Given fields are invalid

Magic RPC Error: [-32603] Internal error: Given fields are invalid: ['provider_id']

⁠This error will be thrown if you try calling loginWithOIDC and pass in an incorrect providerId.

Given federated identitytoken is invalid or malformed

Magic RPC Error: [-32603] Internal error: Given federated identity token is invalid or malformed

This error can be thrown when the OIDC token is invalid in some way. The token could simply be malformed, or the token could be correct, but has mismatched provider claims. In other cases, depending on the identity provider, the Issuer Domain may require a slash to be appended or removed. It could also be that the sub does not match the provider sub.

#Resources