# Login with Link (auth back-end only)

To be clear, this is just a fun hack for now. Yes, it works! No, it's not official (from Stripe). Yes, I might change it to break at any time.

*For now, all responsibilty for anything breaking should be directed to <m@rkmoriarty.com>.*

### Questions?

* If you work at Stripe: Ask questions on #login-with-link.&#x20;
* Otherwise, email <markmoriarty+loginwithlink@stripe.com> 👋

## Sunday 5/22: These docs will describe how to use this via API only.&#x20;

You will bring your own session management library (e.g., authjs.dev, as used on shop.markmoriarty.com)

The main steps are quite simple:

1. `/lookup`  Collect a user's email for login or signup: Look up this email to see if the email exists on the Link network. We will send you a `client_secret` in our response.

*(If the user does NOT exist on Link: invite them to sign up for Link. Otherwise, continue with the below.)*

* `/start_verification` If the user does exist on Stripe: ask Stripe to send them the SMS verification code.&#x20;

2. `/authenticate` Collect the 6-digit code from the user using a form of your own design. Submit this to Stripe, along with the \`client\_secret\` we sent you in step 1.

Click "next" to view instructions to use API only: <https://docs.loginwithlink.com/use-api-only/about-this-option-api-only>&#x20;

## In a few days(?): Plausibly I could spin up a basic OIDC provider

Redirect from your site to a Stripe-hosted "Login with Link/Stripe" page, just like you'd do for "Log in with Twitter" or "Log in with GitHub".&#x20;

Wish: rally >1 other Stripes to have other session-management front-ends (ideally not also using next-auth.js), using this new (minimal) OIDC provider. This should help demonstrate (to less technical folks) how to separate "Login with Link" (as just OIDC) from "session management" (using libraries like next-auth, firebase, supabase, etc.)

Based on today's research, it seems quite doable. Stripe out the front-end pages like /users, and do a redirect instead of log in action, so developer can B.Y.O. session management library: [read more](https://docs.loginwithlink.com/oidc-oauth-hosted-login-page/about-this-option-open-id-connect-oidc).<br>


# About this option: API only

"Use API only" means you build ALL the login forms yourself.

This is what [shop.markmoriarty.com/login](https://shop.markmoriarty.com/login) does.

If you'd like to re-create this, auth flow fully hosted on your website with no redirects, follow this step.

If instead you want an OIDC experience (redirect the user to Log in with Link, just like you'd redirect the user to "Log in with Twitter), see the ["OIDC / OAuth" option](https://docs.loginwithlink.com/oidc-oauth-hosted-login-page/about-this-option-open-id-connect-oidc) instead.


# Lookup email

Check if user exists on Link network

Quick example: <https://loginwithlink.com/api/lookup-email?email=m@rkmoriarty.com&STRIPE_PUBLIC_KEY=pk_live_51JocsEAGmp0k5LnwNUl7SJzZMhMMcMJ4X4PWg928nJLm5ocPpzHLhBOBMbTLBrXPYdkepbg9HX0AJFY8ixt2bXTV00vg5Ja3DP> <- That uses my public key — please use your own once you get the idea!

## Request

This is a GET request.

```
GET https://loginwithlink.com/api/lookup-email
```

Include the following query parameters

| Parameter           | Example                                                                                                       |
| ------------------- | ------------------------------------------------------------------------------------------------------------- |
| email               | <m@rkmoriarty.com>                                                                                            |
| STRIPE\_PUBLIC\_KEY | pk\_live\_51JocsEAGmp0k5LnwNUl7SJzZMhMMcMJ4X4PWg928nJLm5ocPpzHLhBOBMbTLBrXPYdkepbg9HX0AJFY8ixt2bXTV00vg5Ja3DP |
|                     |                                                                                                               |

In total, your request will look like this

```
GET 
https://loginwithlink.com/api/lookup-email?email=m@rkmoriarty.com&STRIPE_PUBLIC_KEY=pk_live_51JocsEA_YOUR_KEY_HERE
```

e.g., if using \`fetch\`, you might compose a request like so:

```javascript
const url = "https://loginwithlink.com/api/lookup-email";
const queryParams = {
  email: "m@rkmoriarty.com",
  STRIPE_PUBLIC_KEY: "pk_live_51JocsEAGmp0k5LnwNUl7SJzZMhMMcMJ4X4PWg928nJLm5ocPpzHLhBOBMbTLBrXPYdkepbg9HX0AJFY8ixt2bXTV00vg5Ja3DP"
};

const queryString = Object.entries(queryParams)
  .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
  .join("&");

const fullUrl = `${url}?${queryString}`;

fetch(fullUrl)
  .then(response => response.json())
  .then(data => {
    // Handle the response data here
    console.log(data);
  })
  .catch(error => {
    // Handle any errors that occur during the fetch request
    console.error(error);
  });
```

##

## Response

The response will look something like this, if a match is found:

```json
{
  "result": "success",
  "parametersSubmitted": {
    "email": "m@rkmoriarty.com",
    "STRIPE_PUBLIC_KEY": "pk_live_51JocsEAGredacted [you provided in your request]"
  },
  "userExistsOnLink": true, // or false, if user not found on Link
  "client_secret": "ABCD1234redacted" // Keep this handy; you'll need to re-submit in the final step
  "redacted_phone_number": "+3*********90" // you may wish to display this: "SMS has been sent to…"
}
```

You will see `"userExistsOnLink": false` if user is not found on Link.


# Start verification

"Start verification" means "ask Stripe to send the six-digit code"

## Request

POST to the following URL

```
POST https://loginwithlink.com/api/start_verification  
```

Include:

* The \`client\_secret\` you received in step 1 (lookup).
* The \`email\` of the consumer.

## Response

The response will confirm that an SMS has been sent, and will again show you redacted phone number to which it has been sent.

(You can display this phone number to your user.)

### Notes

* For now this is a separate step.
  * You might want to check if the user exists on Stripe just to update the button text from "Sign up" to "Log in".
* Or, (to think about this), we could have this combined with the previous step.
  * In fact, that might be a good idea… so a merchant doesn't look up loads of emails without risking spamming all their users with surprise (and concerning) SMS codes.


# Authenticate

"Authenticate" means "Let the user enter their 2FA code to Stripe, and tell me if they authenticated correctly"

## Request

POST to the following URL

```
POST https://loginwithlink.com/api/authenticate
```

Include:

* The \`client\_secret\` you received in step 1 (lookup).
* The \`email\` of the consumer.
* The six-digit code they have entered.

## Response

### If six-digit code is correct

We'll return a user object along with `` `authenticationSuccessful: true` ``&#x20;

```json
// if user code is correct
{ authenticationSuccessful: true,
  user: {
    email: "m@rkmoriarty.com"
  }
}
```

If you've been pre-approved, and if the user has such information saved, the user object may be enhanced with additional information:

```json
{ authenticationSuccessful: true,
  user: {
    email: "m@rkmoriarty.com",
    fullName: "Mark Moriarty",
    city: "San Francisco, California 94114",
  }
}
```

### If the six-digit code is not correct:

We'll return `` `authenticationSuccessful: false` `` along with an an error message.

```json
{ authenticationSuccessful: false,
  errorMessage: "m@rkmoriarty.com"
}
```


# About this option: Open ID Connect (OIDC)

This approach uses OAuth.

How it works:

I could split out the UI + login logic to be a separate auth end only, which instead of "logging someone in" if they input the correct code, "redirect them" if they input the correct code. You, a the website developer, then "log them in" at your end. \
This options allows any developer (e.g., another Stripe building a demo site, or \~10 non-Stripe developers we show this to) to use this social login option to add "Log in with Link" to any website that supports OAuth (e.g., websites built with Firebase, Clerk, AuthJS.dev, Supabase, etc.)

To use this, you'll:

* Have a button your your website that says "Log in with Link"
* Clicking that button redirects the user to a page hosted on loginwithlink.com
* We authenticate the user, then redirect them back to your site with a code/token.
* You use that code to validate with us (via API) that the user is in fact logged in.

Examples:

* This is what <https://shop.markmoriarty.com/social-login> uses \[TODO]
* This is what \[another demo website built by another Stripe?] uses \[TODO]
* This is what \[another demo website built by another Stripe?] uses \[TODO]


# OIDC / OAuth

To do!

See also

* <https://accounts.google.com/.well-known/openid-configuration>&#x20;
* <https://next-auth.js.org/configuration/providers/oauth>&#x20;

\[ToDo] Basically just clone shop.markmoriarty.com and strip out all the non-auth pages (/users, /protected, etc.) — leave the "login page" and redirect after login. Rough schematic (replace GitHub with LoginWithLink).

![](https://1532429786-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9FJWBnQbpPhY5ZKD2AIy%2Fuploads%2Fw9xOCQFGLC7pyAqoXR2T%2Fimage.png?alt=media\&token=41be0395-d08f-4512-a0a5-8e2457554672)

![](https://1532429786-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9FJWBnQbpPhY5ZKD2AIy%2Fuploads%2FhNFw78rX6vqerI3vO2xt%2Fimage.png?alt=media\&token=733996a8-0472-4322-a3de-12beed6ea5c1)


