## 1. Project Overview & Quickstart (simple-login/example.env)

# example.env

Open-source repository simple-login/example.env

### Repository Details
- **Repository:** [simple-login/example.env](https://github.com/simple-login/example.env)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (simple-login/docs)

## File: README.md

To get hugo theme

```bash
git submodule update --init --recursive
```

To deploy:

```bash
hugo && vercel --prod
```

To dev locally

```bash
hugo server
```

Then open http://localhost:1313

---

## File: content/docs/app.md

# App

## What is a SimpleLogin App?

A SimpleLogin App represents an **user database**. For ex, if you have iOS, Android and Web app for a single product, then you just need a single SimpleLogin App. Same applies if you have 2 different products but that share the same user database.

## Create an App

Please head to https://app.simplelogin.io/developer/ and click on **Create new app** to create a new app. You only need to provide a name.



All app fields are optional. We recommend however to provide as much information as possible so user can recognize your app. Teaser: a **showcase** feature is in progress and once the feature is ready, you can submit your app to the showcase to promote it to all SimpleLogin users.

Depending on the flow you choose (`code` or `implicit`), you would need store either:

- both `oauth client id` and `oauth client secret` if you decide to use `code flow`

- or just `oauth client id` if you choose `implicit flow`

To have a shorter terminology, `AppID` and `oauth client id` are the same thing and so are `AppSecret` and `oauth client secret`.

## App Redirect URI

This is the most important field in your app! By default SimpleLogin **whitelists** all `http[s]://localhost:*` address to facilitate local development but you need to set your app `Redirect URI` before deploying your app to production: in effect, SimpleLogin will refuse to present the **Authorization Page** to user if it doesn't recognize the `redirect_uri` passed in the `url`. You can add as many `redirect uri` as you want. Please note that except the localhost ones, the `Redirect URI` needs to be **https** for security reason.



When some errors happen during the authorization flow, SimpleLogin redirects user back to `redirect_uri?error={error_code}` so your app can act accordingly. Please find the list of all errors on [Error Codes]({{< relref "/docs/errors.md" >}}).

## Libraries/Framework

SimpleLogin has added support for SimpleLogin in the following popular libraries and more are coming:

- Vanilla JS (`Implicit Flow`): [hello.js](https://github.com/MrSwitch/hello.js), [JSO](https://github.com/andreassolberg/jso)
- Python (Flask and other non-Django frameworks): [Requests-OAuthlib](https://github.com/requests/requests-oauthlib)
- Django: [social-auth-app-django](https://github.com/python-social-auth/social-app-django)
- NodeJS [Passport](https://github.com/jaredhanson/passport)

It's impossible to cover all Social Login libraries for all languages. As SimpleLogin implements fully OAuth2/OpenID Connect standard, any library compatible with these standards should be able to handle SimpleLogin with the following OAuth2/OpenID Connect endpoints:

- Authorization endpoint: https://app.simplelogin.io/oauth2/authorize
- Token endpoint: https://app.simplelogin.io/oauth2/token
- UserInfo endpoint: https://app.simplelogin.io/oauth2/userinfo

Please find in the **Guides** section dedicated guide for some frameworks/languages.

If you don’t want to use a library that supports OAuth/OpenID Connect, this can work too! Please head to

- [Code Flow - The raw way]({{< relref "/docs/code-flow.md" >}}) for implementing the `Code Flow`
- [Implicit Flow - The raw way]({{< relref "/docs/implicit-flow.md" >}}) for implementing the `Implicit Flow`

---

## File: content/docs/code-flow.md

# Code Flow - the raw way

If you don't use (or don't want to use a library that supports OAuth/OpenID Connect), you totally can! The protocol is actually quite simple from the app's point of view. (the spec is hundreds pages for provider though ...)

This section will explain how to implement the `Code Flow` in your back-end along with some info to watch out for.

To implement the `Code Flow` please make sure you have:

- read through the [Introduction]({{< relref "/" >}}) to have a rough idea on what is the `Code Flow` and
- followed the [App]({{< relref "/docs/app.md" >}}) to have the SimpleLogin AppId and AppSecret.

As recommended in the [The Twelve Factors](https://12factor.net), let's export these values into env variables:

```bash
export CLIENT_ID={your_app_id}
export CLIENT_SECRET={your_app_secret}
```

The way to read these env variables in the code differs from language to language, a quick google `read env var {your language}` should return some results.

To implement the `Code Flow`, you would need 2 endpoints:

1. Login endpoint: that redirects user to SimpleLogin authorization page
2. Callback endpoint: user is redirected back to this page along with a `code` that allows you to exchange for an `access token` which in turn can be used to obtain `user info`.

Let's jump into each endpoint.

## Login endpoint

This endpoint handles user clicking on **Sign in with SimpleLogin** button (e.g. `[Sign in with SimpleLogin](https://your-app/login)`) and redirects user to a **formatted** SimpleLogin url. This url has the following format. Line breaks are added for visibility, please remove them in your code.

```text
https://app.simplelogin.io/oauth2/authorize
    ?response_type=code
    &client_id=CLIENT_ID
    &redirect_uri=REDIRECT_URI
    &scope=profile
    &state=STATE
```

Let's split this long url down to components:

- `response_type=code`: indicates the flow. Its value is `code` for `code flow` and `token` for `implicit flow`. In our case, it's always `code`.
- `client_id=CLIENT_ID`: `CLIENT_ID` is your SimpleLogin AppID. In OAuth terminology, `client` is actually your app.
- `redirect_uri=REDIRECT_URI`: upon user approval, user will be redirected to this url. This should be the url of your callback endpoint that we are going to create in the next step. If your app is https://my-app.com on production and http://localhost:8000 locally, this url would probably be https://my-app.com/callback when you deploy your app on production. Please make sure to add this redirect url on your SimpleLogin Developer page. (see [App]({{< relref "/docs/app.md" >}}))
- `scope=profile`: the user information you want. SimpleLogin supports only `profile` scope which contains user email, name and avatar.
- `state=STATE`: this `STATE` value should be generated **randomly** to avoid CSRF attack. This value will be checked in the callback endpoint and one standard way is to save this value into the cookie that you can retrieve later in the callback endpoint.

## Callback endpoint

Upon user approval, they will be redirected to this below url. Line breaks are also added here for visibility only, please remove them in your code.

```text
REDIRECT_URI
    ?code=CODE
    &state=STATE
```

Let's break the components down:

- `REDIRECT_URI` the same `REDIRECT_URI` in the login endpoint
- `STATE`: the state generated in the login endpoint. It's your app's responsibility to compare this `STATE` to the one generated in previous step, typically by retrieving it from the cookie.
- `CODE`: used to exchange for the `access token` in a POST request to SimpleLogin:

```bash
curl -X POST https://app.simplelogin.io/oauth2/token \
    -F 'grant_type=authorization_code' \
    -F 'code=CODE' \
    -F 'redirect_uri=REDIRECT_URI' \
    -F 'client_id=CLIENT_ID' \
    -F 'client_secret=CLIENT_SECRET'
```

`REDIRECT_URI` is sent once again. The `CLIENT_ID` and `CLIENT_SECRET` are retrieved from env variable.


SimpleLogin will return this response if everything is correct:

```json
{
    "access_token": "LONG_STRING",
    "expires_in": 3600,
    "scope": "profile",
    "token_type": "Bearer",
    "user": {
        "avatar_url": "https://avatar.png",
        "client": "YOUR_APP_NAME",
        "email": "EMAIL@simplelogin.co",
        "email_verified": true,
        "id": 36,
        "name": "FIRST LAST",
        "sub": "36"
    }
}
```

With this user info, you should now either be logged in or have access to some reserved information.

Congratulations, you just implemented a OAuth client!

---

## File: content/docs/discourse.md

# Add SIWSL (Sign in with SimpleLogin) to Discourse
---

[Discourse](https://www.discourse.org) is a popular open-source forum software.

After adding SIWSL to Discourse, a person can choose to use their SimpleLogin account to log in or sign up on your forum 👇



and they can control which information they want to share:



Adding SIWSL is done in 3 simple steps.

## Step 1: Install the OpenID Connect Authentication Plugin

First, let's install the official OpenID Connect Authentication plugin by adding this line

```
sudo -E -u discourse git clone https://github.com/discourse/discourse-openid-connect.git
```

into your container’s `app.yml` file (usually present in `/var/discourse/containers/`). More info on how to install a plugin on [How to Install Plugins in Discourse](https://meta.discourse.org/t/install-plugins-in-discourse/19157)

```
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - sudo -E -u discourse git clone https://github.com/discourse/docker_manager.git
          - sudo -E -u discourse git clone https://github.com/discourse/discourse-openid-connect.git
```

After that rebuild the container.

```bash
cd /var/discourse
./launcher rebuild app
```

The plugin should be now available on the Discourse Admin/Plugins page



---

## Step 2: Create a website on SimpleLogin dashboard

Head to [SimpleLogin dashboard](https://app.simplelogin.io/developer/) and create a new website.



Now go to the **OAuth2 endpoints** page:

- Note the **Client ID** and **Client Secret** needed for the next step.

- Add `{your forum url}/auth/oidc/callback` as **redirect_uri**, make sure to replace `{your forum url}` by your actual forum URL.




---

## Step 3: Config Discourse OpenID Connect Authentication Plugin

Go to the Discourse admin page for Discourse OpenID Connect Authentication Plugin



then make sure to

- enable OpenID Connect
- copy https://app.simplelogin.io/.well-known/openid-configuration in **openid connect discovery document**
- copy your **Client ID** in step 2 to **openid connect client id**
- Copy your **Client Secret** in step 2 to **openid connect client secret**



Lastly, modify the plugin title to "Sign in with SimpleLogin" by editing the text (pointed by the arrow 👆)



## Enjoy!

Now SIWSL should be provided as a login/register option on your forum. Your community members now have a choice of using a privacy-focused, open-source login solution 🎉.

---

## File: content/docs/errors.md

# Possible error codes

When some errors happen during the authorization flow, SimpleLogin redirects user back to `redirect_uri?error={error_code}` so your app can act accordingly. Some errors are often caught during development but some can come from the user. Please find below the complete list of errors:

- `deny`: probably the most frequent error. This happens when user denies sharing their info with your app. You can maybe in this case offer another sign-in mechanism to user, or if SimpleLogin is the only one, let user know that they need to accept sharing their data in order to use your app.

- `invalid_client_id`: this happens when the provided `client_id` is unknown or empty. It can happen when the `client_id` is not set correctly in the code. As a reminder, the authorization url has the following format:

```text
https://app.simplelogin.io/oauth2/authorize
        ?response_type=[code|token]
        &client_id=CLIENT_ID
        &redirect_uri=REDIRECT_URI
        &scope=profile
        &state=STATE
```

- `http_not_allowed`: by default, `http[s]://localhost:*` is whitelisted to facilitate development. However once the *Sign in with SimpleLogin* code hits the production, a correct `redirect_uri` needs to be set on developer page (cf [App]({{< relref "/docs/app.md" >}})). For security reason, `http` is not allowed so you must use `https` for the web. For mobile apps, a custom scheme (e.g. `com.my_company.my_app://`) is also allowed.

- `unknown_redirect_uri`: the `redirect_uri`, if other than `http[s]://localhost:*` needs to be set on developer page. Please see [App]({{< relref "/docs/app.md" >}}).

---

## File: content/docs/flask.md

# Flask

For Flask applications, we recommend [Requests-OAuthlib](https://github.com/requests/requests-oauthlib), a library to integrate OAuth providers. This library is also used by [social-app-django](https://github.com/python-social-auth/social-app-django) to add social login buttons to Django apps

The code example is on https://github.com/simple-login/flask-example.

## Preparation
First please install `Requests-OAuthlib`:

```bash
pip3 install requests_oauthlib
```

Then please store your SimpleLogin **AppID** and **AppSecret** somewhere, preferably in `env` variable as recommended in the [The Twelve Factors](https://12factor.net).

```bash
export CLIENT_ID={your_app_id}
export CLIENT_SECRET={your_app_secret}
```

Bootstrap the app

```python
import requests_oauthlib, os, flask

# Get SimpleLogin AppID, AppSecret from env vars
CLIENT_ID = os.environ.get("CLIENT_ID")
CLIENT_SECRET = os.environ.get("CLIENT_SECRET")

app = flask.Flask("my-app")
app.secret_key = "my-super-secret"  # for flask.session

# This allows us to test the app using HTTP.
# Please make sure to disable it in production
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
```

## Login endpoint

When user clicks on **Sign in with SimpleLogin**, user gets redirected to the SimpleLogin authorization page. This is done using the `/login` endpoint. The `state` is necessary to defend against [CSRF attack](https://www.shellvoide.com/hacks/cross-site-request-forgery-attack-on-oauth2-protocol/).

```python
import requests_oauthlib, os, flask

@app.route("/login")
def login():
    sl = requests_oauthlib.OAuth2Session(
        CLIENT_ID,
        # this supposes you are running your app on the default port 5000
        redirect_uri="http://localhost:5000/callback",
    )

    redirect_url, state = sl.authorization_url(
        "https://app.simplelogin.io/oauth2/authorize"
    )

    # State is used to prevent CSRF, keep this for later.
    flask.session["oauth_state"] = state

    return flask.redirect(redirect_url)
```

## Callback endpoint

When user approves sharing data with your app, they get redirected back to the `redirect_uri` in the previous step. This route is handled by an endpoint that receives the `code` and exchanges for `access token`. The `access token` is then used to exchange for user info:

```python
@app.route("/callback")
def callback():
    sl = requests_oauthlib.OAuth2Session(
        CLIENT_ID, state=flask.session.get("oauth_state")
    )
    # Get the "access token"
    sl.fetch_token(
        "https://app.simplelogin.io/oauth2/token",
        client_secret=CLIENT_SECRET,
        authorization_response=flask.request.url,
    )

    user_info = sl.get("https://app.simplelogin.io/oauth2/userinfo").json()

    # This is where you log user in,
    # for ex via flask-login extension: login_user(user)
    return f"""
    Welcome {user_info["name"]} 
    Your email is {user_info["email"]} 
    And your avatar: 
    """
```

## Run the App and enjoy!

Let's run the app

```bash
flask run
```

Now you should be able to SLWSL at http://localhost:5000/login

---

## File: content/docs/frontend-js.md

# Frontend JS

For Frontend JS (as opposed to Backend Node.js) you can use the **Implicit Flow** to log user in.

We recommend using [SimpleLogin JS SDK](https://github.com/simple-login/sdk.js), which is actually a thin layer over [hello.js](https://github.com/MrSwitch/hello.js). For this reason, you can also use `hello.js` if you app already uses this library.

For the web, there are 2 ways to use SimpleLogin in terms of user experience:

- With popup: when clicking on **Sign in with SimpleLogin** a new window popup is opened and closed once user approves.

{{< figure src="/images/popup.png" caption="With Popup" >}}

- Without popup: in the same window/tab user is redirected to SimpleLogin authorization page and returns back to your app once they approves.

We recommend the **with popup** way so you don't have to deal with state saving when browser reloads in **without popup**.

By default, the **SimpleLogin JS SDK** uses the **with popup** way.

Please find below different ways to add SimpleLogin into your webapp:

- [SimpleLogin JS SDK](https://github.com/simple-login/sdk.js)
- [oidc-client](https://github.com/IdentityModel/oidc-client-js)

## SimpleLogin JS SDK

First include it in your html:

```html
<script src="https://simplelogin.io/sdk/sdk.js"></script>
```

In your `js`, you need to init the SDK with your SimpleLogin AppID:

```js
SL.init("{your SimpleLogin AppID}");
```

To open the login popup, use `SL.login()` which takes a callback as parameter: the callback will receive user info when they approves on SimpleLogin authorization page.

```js
SL.login(function(user) {
    console.log("got user from SL SDK", user);
})
```

The `SL.login` is typically called inside a function onclick:

```js
document.getElementById("btn-simplelogin").onclick = function(e) {
  SL.login(function(user) {
      console.log(user)
  })
}
```


## OIDC Client

[oidc-client](https://github.com/IdentityModel/oidc-client-js) adds OpenID Connect (OIDC) and OAuth2 protocol support for browser-based JavaScript applications.

This library is behind [redux-oidc](https://github.com/maxmantz/redux-oidc) for ReactJS / Redux, [vuejsoidcclient](https://github.com/joaojosefilho/vuejsOidcClient) for Vue.js, [Angular2OidcClient](https://github.com/jmurphzyo/Angular2OidcClient) for Angular, so if you use these web libraries, adding SimpleLogin should be a matter of changing `authority` setting to https://app.simplelogin.io/.

`oidc-client` is quite a _low-level_ library and offers a lot of flexibility. It separates the login step and the callback step.

Let's start by creating a `index.html`:

```html
start signin
end signin

<script src="https://cdn.jsdelivr.net/gh/IdentityModel/oidc-client-js@1.8/dist/oidc-client.min.js"></script>
```

And add the `js` code, make sure to replace `{your SimpleLogin AppId}` by your AppID.

```js
var settings = {
    // oidc-client will discover all OIDC settings automatically,
    // via https://app.simplelogin.io/.well-known/openid-configuration
    authority: "https://app.simplelogin.io/",
    client_id: "{your SimpleLogin AppId}",
    response_type: 'id_token token',
    // openid in scope to indicate this is OpenID Connect
    scope: 'openid',
    // You need to update this redirect_uri when deploying to production
    redirect_uri: "http://localhost:8000",
}
var mgr = new Oidc.UserManager(settings);

function startSignin() {
    mgr.signinRedirect({state:"some data"}).then(function() {
        console.log("signinRedirect done");
    });
}

function endSignin() {
    mgr.signinRedirectCallback().then(function(user) {
        console.log("signed in", user);
    });
}
```

Now if you run the a local web server (using `python3 -m http.server` for example), you should be able to sign in with SimpleLogin when you open http://localhost:8000

---

## File: content/docs/implicit-flow.md

# Implicit Flow - the raw way

If you don't use (or don't want to use a library that supports OAuth/OpenID Connect), it's OK! The protocol is actually quite simple as you will see shortly below.

This section will explain how to implement the `Implicit Flow` in your front-end using Vanilla JS.

Please make sure you have:

- read through the [Introduction]({{< relref "/" >}}) to have a rough idea on what is the `Implicit Flow` and
- followed the [App]({{< relref "/docs/app.md" >}}) to have the SimpleLogin `AppId`. You don't need the `AppSecret` in this flow.

To implement the `Implicit Flow`, you would need 2 parts in your app:

1. Login part: that redirects user to SimpleLogin authorization page
2. Callback part: user is redirected back to your app along with an `access token` which can be used to obtain `user info`.

Let's jump into each part.

## Login part

This part handles user clicking on **Sign in with SimpleLogin** button (e.g. `Login with SimpleLogin`) and redirects user to a **formatted** SimpleLogin url. This url has the following format. Line breaks are added for visibility, please remove them in your code.

```text
https://app.simplelogin.io/oauth2/authorize
    ?response_type=token
    &client_id=CLIENT_ID
    &redirect_uri=REDIRECT_URI
    &scope=profile
    &state=STATE
```

Let's take a closer look at this long url:

- `response_type=token`: indicates the flow. Its value is `token` for `implicit flow` and `code` for `code flow`. In our case, it's always `token`.
- `client_id=CLIENT_ID`: `CLIENT_ID` is your SimpleLogin AppID. In OAuth terminology, `client` is actually your app.
- `redirect_uri=REDIRECT_URI`: upon user approval, user will be redirected to this url. This is usually the same as your app url. By default SimpleLogin whitelists `localhost` so you don't need to do anything for local development. Please see [App]({{< relref "/docs/app.md" >}}) for more information.
- `scope=profile`: SimpleLogin supports only `profile` scope which contains user email, name and avatar.
- `state=STATE`: this `STATE` value should be generated **randomly** to avoid CSRF attack. This value will be checked in the callback endpoint and one standard way is to save this value into the `sessionStorage` that you can retrieve later in the callback endpoint.

## Callback part

Upon user approval, they will be redirected to this url below. Line breaks are also added here for visibility only, please remove them in your code.

```text
REDIRECT_URI
    #state=STATE
    &scope=profile
    &access_token=ACCESS_TOKEN
```

Let's break the components down:

- `REDIRECT_URI` the same `REDIRECT_URI` in the previous step
- `STATE`: the state generated in the previous step. It's your app's responsibility to compare this `STATE` to the one generated in previous step, typically by retrieving it from the `sessionStorage`.
- `ACCESS_TOKEN`: used to get user info in a POST request to SimpleLogin. You might also notice that `#` is used instead of `?`; this is to avoid the `access token` hitting your back-end (if there's any) in the `implicit flow`.

Here's the code snippet using `fetch` to get user info with the obtained `access token`:

```js
fetch("https://app.simplelogin.io/oauth2/user_info", {
    method: 'GET',
    headers: {
        'AUTHORIZATION': `Bearer ${ACCESS_TOKEN}`
    }
}).then(response => response.json()).then(userInfo => {
    console.log(userInfo);
    alert(`Welcome ${userInfo.name}`);
})

```

SimpleLogin will return this response if everything is correct:

```json
{
    "avatar_url": "https://avatar.png",
    "client": "{Your App Name}",
    "email": "EMAIL@simplelogin.co",
    "email_verified": true,
    "id": 36,
    "name": "FIRST LAST",
    "sub": "36"
}
```

With this user info, you should now either be logged in or have access to some reserved information.

Congratulations, you just implemented the OAuth Implicit Flow!

## Code example

Please find below a full code example for this section. Please make sure to replace `YOUR_APP_ID` by your SimpleLogin AppID and serve the code on port 8000 (or just replace `http://localhost:8000` by your local url). This can be done by saving this code into a `index.html` file and serve the file with Python `http` module:

> python3 -m http.server

or by NodeJS `static-server` tool, can be installed via `npm -g install static-server`

> static-server -p 8000

```html
Sign in with SimpleLogin

<script>
    function simpleLogin() {
        let appId = "YOUR_APP_ID";
        let state  = randomString();

        // save state into sessionStorage to check later in the callback
        sessionStorage.setItem("state", state);

        let url = "https://app.simplelogin.io/oauth2/authorize" +
            "?response_type=token" +
            `&client_id=${appId}` +
            "&redirect_uri=http://localhost:8000" +
            "&scope=profile" +
            `&state=${state}`

        // redirect user to SimpleLogin
        location.href = url;
    }

    // if accessToken is found, then it's the callback
    let accessToken = getQueryParam("access_token");

    if (accessToken) {
        // Check if state has changed
        state = getQueryParam("state");

        if (state != sessionStorage.getItem("state")){
            // CSRF attack
            alert("nice try! Or you need to enable sessionStorage ...");
        }

        // get user info
        fetch("https://app.simplelogin.io/oauth2/user_info", {
            method: 'GET',
            headers: {
                'AUTHORIZATION': `Bearer ${accessToken}`
            }
        }).then(response => response.json()).then(userInfo => {
            console.log(userInfo);
            alert(`Welcome ${userInfo.name}`);
        })
    }

    // utility function to get query value from url
    function getQueryParam(key) {
        var half = location.href.split(key + '=')[1];
        return half !== undefined ? decodeURIComponent(half.split('&')[0]) : null;
    }

    // generate a 15-char string
    function randomString(){
        return Math.random().toString(36).slice(-15);
    }

</script>
```

## Popup or not popup

You might notice that when clicking on **Login with Facebook/Google** button, a new (small) window is opened instead of user leaving your app. This has the advantage of user still staying on your app and therefore you don't need to worry about saving user data before redirecting them to another page.

This can be done quite easily using SimpleLogin SDK JS (see [Frontend-JS]({{< relref "/docs/frontend-js.md" >}})) or using libraries such as [hello.js](https://github.com/MrSwitch/hello.js) or [oidc-client](https://github.com/IdentityModel/oidc-client-js). You can also implement this mechanism yourself using the [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) method. How to implement this is out of scope of this page as it requires some advanced technics but basically that's how it works:

- When user clicks on **Sign in with SimpleLogin**, you open a new window using the [window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) method. You can use the current page as target but usually people use an empty page, let's say `redirect.html` to speed up the load time:

```js
const authWindow = window.open(
        "/redirect.html",'SimpleLoginPopup',
        {}
);
```

On this `redirect.html`, we have the 2 steps login and callback implemented like in the previous section. The only thing that changes is `access token` or `user information` will be sent to the `opener` page, which is your app via `window.opener.postMessage`:

```js
window.opener.postMessage(
  { auth: { token: access_token } },
  window.opener.location
);
```

On your app, you need to setup a event listener that handle this message

```js
window.addEventListener('onmessage', e => {
    if (e.data.auth) {
        // Get user info with the access_token
    }
})
```

Please take a look at this [gist](https://gist.github.com/gauravtiwari/2ae9f44aee281c759fe5a66d5c2721a2) that contains some snippets that can be used to handle data exchange between your app (the main window) and the popup.

---

## File: content/docs/passport.md

# Node.js - Passport

For Node.js application, we recommend [passport](https://github.com/jaredhanson/passport), an authentication middleware for Node.js. Passport supports a comprehensive set of **strategies** including username/password login and social login (Facebook, Twitter, etc).

For SimpleLogin, you can use either [OAuth strategy](https://github.com/jaredhanson/passport-oauth) or [OpenId Connect strategy](https://github.com/jaredhanson/passport-openidconnect). In this guide, we will use the **OpenId Connect Strategy**. The code along with a step-by-step guide is also available on https://github.com/simple-login/passportjs-example

## Preparation

First please install `passport`, `passport-openidconnect`, `express-session` (passport uses session to store its data)

```bash
npm install passport passport-openidconnect express-session --save
```

Then please store your SimpleLogin **AppID** and **AppSecret** somewhere, preferably in `env` variable as recommended in the [The Twelve Factors](https://12factor.net).

```bash
export CLIENT_ID={your_app_id}
export CLIENT_SECRET={your_app_secret}
```

Bootstrap the app:

```js
var express = require('express');

// For Passport
var session = require('express-session');
var passport = require('passport');
var OidcStrategy = require('passport-openidconnect').Strategy;

var app = express();

// passportjs use session to store user info
app.use(session({
  secret: 'my-super-secret',
  resave: false,
  saveUninitialized: true
}));

app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser((user, next) => {
  next(null, user);
});

passport.deserializeUser((obj, next) => {
  next(null, obj);
});
```

## Config SimpleLogin OIDC Provider

Let's tell passport SimpleLogin OIDC (OpenID Connect) setting:

```js
// config SimpleLogin OIDC (OpenID Connect) provider
passport.use('SimpleLogin', new OidcStrategy({
  // SimpleLogin OIDC Settings
  issuer: 'https://app.simplelogin.io',
  authorizationURL: 'https://app.simplelogin.io/oauth2/authorize',
  tokenURL: 'https://app.simplelogin.io/oauth2/token',
  userInfoURL: 'https://app.simplelogin.io/oauth2/userinfo',
  // SimpleLogin App Credential from env
  clientID: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
  // you might need to change the callbackURL when deploying on production
  callbackURL: 'http://localhost:3000/callback',
  // openid needs to be in scope
  scope: 'openid'
}, (issuer, sub, profile, accessToken, refreshToken, done) => {
  return done(null, profile);
}));
```

## Login endpoint

When user clicks on **Sign in with SimpleLogin**, user gets redirected to the SimpleLogin authorization page. This is done using the `/login` endpoint. The nice thing about passport and its OpenID Connect strategy is it also takes care of generating a random `state` in the redirection URL. The `state` is necessary to defend against [CSRF attack](https://www.shellvoide.com/hacks/cross-site-request-forgery-attack-on-oauth2-protocol/).

```js
// redirect user to authorization page
app.use('/login', passport.authenticate('SimpleLogin'));
```

## Callback endpoint

When user approves sharing data with your app, they get redirected back to the `redirect_uri` in the previous step. This route is handled by an endpoint that receives the `code` and exchanges for `access token`. The `access token` is then used to exchange for user info. Passport once again handles all these details nicely:

```js
// user is redirected back
app.use('/callback',
  passport.authenticate('SimpleLogin', {
    failureRedirect: '/error'
  }),
  (req, res) => {
    var user= req.user._json
    res.send(`
      Welcome ${user.name}! 
      Your email: ${user.email} 
      Avatar: 
      `)
  }
);
```

## Run the App and enjoy!

let's finish by adding this to the end:

```js
app.listen(3000, () => console.log(`App listening`))
```

And run the app

```bash
node app.js
```

Now you should be able to sign in with SimpleLogin at http://localhost:3000/login