Embedded Magic Links
Generate login links and deliver them to customers through your own channels.
Magic Links are a great way to provide additional flexibility in your application's authentication system. With Passage, you have the ability to create Magic Links that can be delivered in any way you like - custom email templates, in-app chat messages, or anything else you can think of. Embedding Magic Links in your marketing emails, reminder texts, or other mediums can greatly reduce user friction and increase conversion rates.
Create a Magic Link
Magic Links can be create via any of our backend SDKs or the management API. Authentication with an API Key is required to use this functionality. To create an API Key, visit the Passage Console.
To create a Magic Link, you must provide one of the following:
- User ID
- Email address
- Phone number
If the user does not exist, they will be created before returning the Magic Link.
Node.js
import Passage from '@passageidentity/passage-node';
let passageConfig = {
appID: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
};
let passage = new Passage(passageConfig);
let magicLink = passage.createMagicLink({
email: 'newEmail@domain.com',
redirect_url: '/custom-path/1234',
});
// use magicLink.url
console.log(magicLink.url);
Python
from passageidentity import Passage
psg = Passage(PASSAGE_APP_ID, PASSAGE_API_KEY)
# create a magic link
magicLinkAttributes={
"email": "<example@email.com>",
"redirect_url": "/custom-path/1234"}
magicLink = psg.createMagicLink(magicLinkAttributes)
# use the 'url' parameter
print(magicLink.url)
Go
import (
"github.com/passageidentity/passage-go"
"fmt"
)
func main() {
psg, err := passage.New(PASSAGE_APP_ID, &passage.Config{
APIKey: PASSAGE_API_KEY,
})
createMagicLinkBody := passage.CreateMagicLinkBody{
Email: "anna@passage.id",
RedirectURL: "/custom-path/1234",
}
magicLink, err := psg.CreateMagicLink(createMagicLinkBody)
// use magicLink.URL
fmt.Println(magicLink.URL)
}
cURL
curl --request POST \
--url https://api.passage.id/v1/apps/<PASSAGE_APP_ID>/magic-links \
-H 'Authorization: Bearer <PASSAGE_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"email": "anna@passage.id",
"redirect_url": "/custom-path/1234"
}'
Ruby
require 'passageidentity'
PassageClient = Passage::Client.new(
app_id: PASSAGE_APP_ID,
api_key: PASSAGE_API_KEY
)
magic_link = PassageClient.create_magic_link(user_id: user_id)
magic_link = PassageClient.create_magic_link(
email: "example@domain.com",
send: true,
channel: Passage::EMAIL_CHANNEL,
ttl: 120
)
There are a number of additional optional parameters you can provide to further customize the Magic Links. The full parameter list for the create Magic Link API endpoint is below.
Parameter | Description |
---|---|
user_id: string | [Optional] Passage ID for user. Must provide one of: User ID, Email, Phone |
email: string | [Optional] Email for user. Must provide one of: User ID, Email, Phone |
phone: string | [Optional] Phone number for user. Must provide one of: User ID, Email, Phone |
redirect_url: string | [Optional] Specifies the redirect location for the user after successful authentication. Defaults to the app's redirect URL. |
magic_link_path: string | [Optional] Specifies the location of the Passage Element or Passage-JS instance that will process the authentication. Defaults to the app's login URL. |
send: boolean | [Optional] Specifies if Passage will send the Magic Link or not. Defaults to |
channel: string | [Optional] Required if send is |
ttl: integer | [Optional] The time to live in minutes for the Magic Link. Defaults to the app's Magic Link duration. |
language: string | [Optional] A language string for localizing emails. Defaults to the default language set in Passage Console if not provided or language is unsupported. |
type: string | [Optional] Specify the type of Magic Link to create. Defaults to |
When a magic link is successfully created, the response will look like this. The magic_link.url
value should be embedded into your custom delivery mechanism.
{
"magic_link": {
"id": "tiDy...fb9v",
"secret": "s0uv...Qz3Vm",
"activated": false,
"user_id": "M6SN...If9K",
"app_id": "3drf...lIj1",
"identifier": "anna@passage.id",
"type": "login",
"redirect_url": "/custom-path/1234",
"url": "http://localhost:8080/?psg_magic_link=ml.tiDyzZGmP7C4KbcAGolofb9v.M6SNdnnS6ZRjT2BctV67If9K.s0uvMvelBe6ZM4EfTgzQz3Vm",
"ttl": 60
}
}
Note: If you want to send a user a Magic Link via two different mediums (e.g. email and text), we recommend that you generate two different Magic Links since the link are one-time use only.
Example use cases
Not sure when to use embedded Magic Links? Here are a few use cases we've seen from customers. If you have another interesting application for embedded links tell us more about it in Discord or by emailing us at support@passage.id.
Sending report reminders from an application
Acme has an application that uses Passage for biometric authentication. The application uses email addresses as the primary identifier for logging in. One feature of the application is weekly usage reports for their customers. Acme wants to email customers weekly to remind them to view their reports. They have noticed that their users will click the "View Report" button, but often not log in and they want to "View Report" button to include an embedded link.
Since users need to be logged in to view their report, Acme uses Passage Embedded Links to reduce user friction associated with logging in. The application can include an embedded link in the "View Report" button in the reminder emails. When users click the button, they skip the step where they enter their email and are instead immediately prompted for their biometric to log in and be redirected straight to their report.
Acme creates smart links with the following example code.
import Passage from '@passageidentity/passage-node';
let passageConfig = {
appID: 'ACME_APP_ID',
apiKey: 'ACME_API_KEY',
};
let passage = new Passage(passageConfig);
let magicLink = passage.createMagicLink({
email: 'user1@domain.com',
redirect_url: '/reports/report-1234-5678',
});
// use magicLink.url
console.log(magicLink.url);
"Anonymous" users submitting requests
Acme has an application that allows unauthenticated users to submit requests for a work quote. Users must provide an email address and phone number when submitting their request. Once the internal team has prepared the quote, they submit it to the application then notify the user via email and text.
Since these users do not have accounts on the application, Passage will create an account for them before sending the Magic Links. The application will create two Magic Links - one to send via email and one to send via text - since a Magic Link is one-time use only.
Acme create embedded links with following code.
import Passage from '@passageidentity/passage-node';
let passageConfig = {
appID: 'ACME_APP_ID',
apiKey: 'ACME_API_KEY',
};
let passage = new Passage(passageConfig);
//generate magic link for email address and create user
let magicLink = passage.createMagicLink({
email: 'user1@domain.com',
phone: '+11234567890',
redirect_url: '/quotes/quoteid-1234-5678',
});
// generate another link to send via text, so they are both valid
let magicLink2 = passage.createMagicLink({
user_id: magicLink.user_id,
redirect_url: '/quotes/quoteid-1234-5678',
});
// send this one via email
console.log(magicLink.url);
// send this one via text
console.log(magicLink2.url);
Acme uses a Passage Element to handle the authentication when a user clicks the link to view their quote. If users want to see their quote in the future, they will be able to log in via the Passage Element using device biometrics or Magic Links since they have an account.
Security considerations
The ability generate a Magic Link for any user is a powerful feature, but also comes with security risks if used incorrectly. The Magic Link URL should be carefully protected and only in rare circumstances be returned to the users of your application. The Magic Link URLs should be sent via secure means to your customers, since it provides a direct way to authenticate to your application.