---
title: Magic Links
slug: dev/single-sign-on
docTags: 
createdAt: 2021-10-02T14:00:23.000Z
---

With Magic Links customers can seamlessly sign into your customer portal from your app or website.

Magic Links are a secure passwordless authentication mechanism that lets you securely generate URLs to sign customers into your [customer portal](https://docs.invoiced.com/guides/billing-portal). This is perfect for redirecting users already authenticated within your app or service into your customer portal without the need for them to sign in once more.

## Generating Magic Links

1. Obtain your Magic Link key from the dashboard:
   You can grab the secret key for generating Magic Links for your account in **Settings** → **Developers** → **Magic Links** within the dashboard.

   **WARNING:** Keep your Magic Link key secret! It should only be used on servers under your control and never exposed in client-side code.
2. Generate a sign in token:
   Using your Magic Link key you can generate JWT tokens from your backend that tell us which customer to sign in.
3. Build the URL:
   Now you can plug your freshly generated token into a sign in URL (replace yourcompany with your Invoiced username):

   `https://{yourcompany}.invoiced.com/login/{generated_token}`

   You can now link your freshly generated URL from your website or else redirect users here.

### Page Shortcuts

When you sign your customer into the customer portal you can jump your customer into a sepcific page by adding a `?redirect_to` parameter to the magic link URL. If you do not specify this optional parameter then the user will be redirected to the My Account page by default.

For example, to redirect your customer to the add payment method screen the resulting sign in URL would look like this:

`https://{yourcompany}.invoiced.com/login/{generated_token}?redirect_to=add_payment_method`

| **Page**                                  | **Page ID**                 |
| ----------------------------------------- | --------------------------- |
| My Account                                | `my_account`                |
| Credit Notes List                         | `credit_notes`              |
| Invoices List                             | `invoices`                  |
| Estimates List                            | `estimates`                 |
| Payments List                             | `payments`                  |
| Balance Forward Statement (Current Month) | `balance_forward_statement` |
| Open Item Statement                       | `open_item_statement`       |
| Pay Balance                               | `pay`                       |
| Add Payment Method                        | `add_payment_method`        |
| Update Billing Information                | `update_billing_info`       |

## Generating JWT Tokens with a client library

:::CodeblockTabs
```java
import com.invoiced.util.SingleSignOn;
SingleSignOn magicLink = new SingleSignOn("{YOUR_MAGIC_LINK_KEY}");

int customerId = 1234;
int ttl = 3600; // 1 hour
token = magicLink.generateToken(customerId, ttl);
```

```php
<?php

use Invoiced\Client;
$invoiced = new Client("{YOUR_API_KEY}", false, "{YOUR_MAGIC_LINK_KEY}");

$customerId = 1234;
$ttl = 3600; // 1 hour

$token = $client->generateSignInToken($customerId, $ttl);
```

```ruby


require "invoiced"
client = Invoiced::Client.new("{YOUR_API_KEY}", false, "{YOUR_MAGIC_LINK_KEY}")

customerId = 1234
ttl = 3600 # 1 hour

token = client.generate_sign_in_token(customerId, ttl)
```
:::

## Generating Magic Links without a client library

If you are using a language not supported with an official Invoiced client library then you can still generate Magic Links. The steps to generate a JWT token will vary by language, however, there are many open source libraries that make it a simple process.

Any JWT tokens you generate should be signed using the `HS256` algorithm with your Magic Link key. The token should have the following parameters for the header:

```json
{
 "alg": "HS256",
 "typ": "JWT"
}
```

And the following parameters for the payload:

```json
{
 "sub": "{invoiced_customer_id}",
 "iss": "Ruby Backend",
 "exp": 1455564948
}
```

- The `sub` parameter should be the ID of the customer on Invoiced you are signing the user in as.
- The `iss` parameter should be a string to identify the service that generated the token (any value works here).
- The `exp` parameter should be a [UNIX timestamp](https://en.wikipedia.org/wiki/Unix_time) to indicate when the URL should expire.

This will generate a token similar to this:

`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiUnVieSBCYWNrZW5kIiwiZXhwIjoxNDU1NTY0OTQ4fQ.LXu-zcMTF8ikMSRrSVYnP0szyRZuqQOAorHAsDrfwPs`

We recommend taking a look at [jwt.io](https://jwt.io) to verify that tokens you generate are valid and to find client libraries in your language.

### Example

Here is an example showing how to generate a Magic Link in Ruby with the `jwt` gem (as opposed to using the invoiced-ruby library):

```ruby
require 'jwt'

magic_link_key = '{magic_link_key_from_dashboard}'

exp = Time.now + 86400 # link expires in 1 day

payload = {
:sub => 1234, # invoiced customer ID
:iss => "Ruby Backend",
:exp => exp.to_i
}

token = JWT.encode payload, magic_link_key, 'HS256'

# eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEyMzQsImlzcyI6IlJ1YnkgQmFja2VuZCIsImV4cCI6MTQ1NTY1MjIxMH0.7kClQ2UAVEZ7xYus7ZHGRePnzDG5mBrcgIo6rZuo-Dw
puts token

url = "https://yourcompany.invoiced.com/login/#{token}"

# https://yourcompany.invoiced.com/login/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEyMzQsImlzcyI6IlJ1YnkgQmFja2VuZCIsImV4cCI6MTQ1NTY1MjIxMH0.7kClQ2UAVEZ7xYus7ZHGRePnzDG5mBrcgIo6rZuo-Dw
puts url
```

