Authenticate With Backend Server

Once you sign a user in with Swoop, you need to validate their id_token with your Swoop secret on your backend server to complete the login process. This is necessary to prevent a nefarious party from intercepting your request and logging in as your user.

After validating the id_token of the user, you are free to log them into your app. Logging in a user can mean different things to different apps. For an SSR (server-side rendering) app, you would most likely look up the user and create a new session. For a CSR (client-side rendering) app, you would return an access token for YOUR app.

Send The ID Token To Your Server

Below is some sample code for sending your Swoop id_token to your server with an endpoint of /auth/swoop.

function swoopOnSuccess(user) {
  // Get the user's id_token
  let id_token = user.id_token;

  // Set up the request
  let xhr = new XMLHttpRequest();
  xhr.open('POST', 'https://yourwebserver.com/auth/swoop');
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  // Success callback for the request. Redirect the user to their account
  xhr.onload = function() {
    console.log("Server response:");
    console.log(JSON.parse(xhr.responseText));
    // location.href = '/account';
  };
  // Send the request with the post body of idToken=id_token
  xhr.send('idToken=' + id_token);

}

Validate The ID Token

The id_token returned from Swoop is a JSON Web Token (JWT) which is signed with your client secret. To validate the token and get the user's email from the payload, you can use your favorite JWT library in the programming language of your application server. Below are a few code examples for different languages.

// yarn add jsonwebtoken

const jwt = require('jsonwebtoken');
const swoop = async(req, res) => {
const token = req.body.idToken;
const secret = "SWOOP_SECRET";
const clientId = "SWWOP_CLIENT_ID";
const issuer = "https://auth.swoop.email";

try {
  let payload = await jwt.verify(token, secret, { audience: clientId, issuer: issuer });
  const email = payload.email;
  const uid = payload.sub;
  // TODO: Lookup user by email or uid and create a session for them
} catch (error) {
  // Invalid id_token return 401
}
};
// composer require firebase/php-jwt

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

// Get $id_token via HTTPS POST.
$clientId = "SWOOP_CLIENT_ID";
$key = "SWOOP_SECRET";
try {
  $payload = JWT::decode($id_token, new Key($key, 'HS256'));
  if ($payload->aud != $clientId) {
    // invalid client_id return 401
  }
  $email = $payload->email;
  $uid = $payload->sub;
	// TODO: Lookup user by email or uid and create a session for them  
} catch (\Exception $e) {
	// invalid id_token return 401
}
# gem jwt

require 'jwt'

def swoop
  # Get the token from the post body
  idToken = params['idToken']       
  secret = SWOOP_SECRET;  
  clientId = SWOOP_CLIENT_ID;
  issuer = "https://auth.swoop.email";
  payload = JWT.decode(idToken, secret, true, { algorithm: 'HS256' })

  # Check the payload for the clientId
  if payload[0]['aud'] != clientId
    render json: { error: 'Invalid clientId' }, status: :unauthorized
    return
  end

  # Check the payload for the issuer
  if payload[0]['iss'] != issuer
    render json: { error: 'Invalid issuer' }, status: :unauthorized
    return
  end
  
  # TODO: Lookup user by email or uid and create a session for them  

  msg = {:email => payload[0]['email'], :uid => payload[0]['sub']}
  render :json => msg
end
import jwt

@app.route('/auth/swoop', methods=['POST'])
@cross_origin()
def swoop():
    token = request.form.get("idToken")
    secret = "SWOOP_SECRET";  
    clientId = "SWOOP_CLIENT_ID";
    issuer = "https://auth.swoop.email";
    decoded = jwt.decode(token, secret, issuer=issuer, audience=clientId, algorithms=["HS256"])
    response = {
        "email" : decoded["email"],
        "uid": decoded["sub"]
    }
    return jsonify(response)

Calling The Token Info Endpoint

During testing, you might not want to spin up your backend to validate tokens. You can always use Swoop's provided API endpoint and call it from your front end. Simply make a GET request to the URL below to validate a user's id_token.

https://api.swoop.email/api/v1/tokens/info?id_token=ABC123

If the token is valid, this endpoint will return the contents of the JWT as well as validate it with your app's secret so you can be sure that the token is valid.

{
"sub": "5e1f795661381c2ad70a8729",
"aud": "swoop_jajh4ki53p7sg",
"iss": "https://auth.swoop.email",
"iat": 1654014797,
"exp": 1656606797,
"type": "id",
"email": "[email protected]"
}

Create A User Session

Once you have validated the user's id_token with your backend server, you should look them up in your database based on their uid or their email. If they exist, create a session for them and redirect them on the client side. If they don't exist, create them in your database and redirect them to fill out their profile information.