pauldps / gfa-sessions-ds

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

THIS PROJECT HAS BEEN DISCONTINUED.

Read more here.

Original README archived below.


@gfa/sessions-api

This component allows creating a session management API using Google Cloud HTTP Functions.

It relies on the following dependencies:

Usage

Create a new Google Cloud Function:

Google Cloud Function Setup

  1. The name of your Google Cloud Function will also be the endpoint name. So, if you name your function "session", the endpoint served will also be called "session". You can name it anything you like.

  2. Select HTTP Trigger.

  3. In the inline editor, paste the following code:

const SessionsApi = require('@gfa/sessions-ds')

const api = new SessionsApi()

exports.handleRequest = function (req, res) {
  api.handle(req, res)
}
  1. Click package.json tab.

  2. Paste the following code (ajust name and version to your liking):

{
  "name": "your-function",
  "version": "0.0.1",
  "dependencies": {
    "@gfa/sessions-ds": "github:pauloddr/gfa-sessions-ds"
  }
}
  1. Set the Entry Point to handleRequest. If you want to use another name, make sure to adjust it in your function code (Step 3).

  2. Click More to show Advanced Options.

  3. Create an environment variable called GFA_SESSION_SECRET containing the secret used to generate the encrypted session cookie. Without this, the function won't start.

  4. Click Create to deploy the function.

After the deploy is finished, the following endpoints will be served (assuming you named your function "session" in step 1):

  • POST /session - creates a new session (user sign-in)
  • GET /session - returns information about current session
  • DELETE /session - destroys session (user sign-out)
  • OPTIONS /session - returns headers

Requirements

This package reads user data from Google Datastore. As such, Datastore must be enabled in the Google Project, and user data should already exist.

Refer to Configuration to determine which Datastore Kind and properties will be used for fetching and verifying user data.

API

This section details the endpoints served by the function.

A function name of "session" is used in examples. If your function has a different name, endpoints will have that name instead.

User Sign-In

  • POST /session

This endpoint creates a new session if provided username/password are valid.

Successful responses set a cookie in the browser (or client) with the session credentials.

Request BodyResponse
// valid credentials
{
  "username": "MyUsername",
  "password": "abc123"
}
// statusCode: 201 Created
{
  "id": "12345",
  "username": "MyUsername"
}
// non-existing username or wrong password
{
  "username": "MyUsername",
  "password": "wrongpass"
}
// statusCode: 401 Unauthorized
// empty response

Please note that if you use custom field names, you must use those modified names in the request body as well. All responses will also present the custom names.

Example for custom fields named user and pass:

Request BodyResponse
// valid credentials
{
  "user": "MyUsername",
  "pass": "abc123"
}
// statusCode: 201 Created
{
  "id": "12345",
  "user": "MyUsername"
}

Current Session Information

  • GET /session

Reads the session cookie and responds with friendly data.

ContextResponse
Session cookie present
// statusCode: 200 OK
{
  "id": "12345",
  "username": "MyUsername"
}
Session cookie not present
// statusCode: 401 Unauthorized
// empty response

To add more user fields to the output of a successful response, set session.expose with an array of field names. It defaults to the user id only.

Setting this option will overwrite the defaults. The example below will remove id from responses, keep username, and add createdAt:

const api = new SessionsApi({
  session: {expose: ['username', 'createdAt']}
})

User Sign-Out

  • DELETE /session

Signs a user out, removing the session cookie from the browser/client.

Request BodyResponse
(empty)
// statusCode 204 No Content
// empty response

Preflight Requests

  • OPTIONS /session

Some clients will fire a "preflight request" prior to making the real request to verify CORS options and other security headers.

Request BodyResponse
(empty)
// statusCode 204 No Content
// empty response with CORS and other security headers

Configuration

Settings can be set upon creating an instance. See defaults below.

var api = new SessionsApi({

  // Session management options
  session: {

    // REQUIRED! if not present, function will intentionally crash
    secret: process.env['GFA_SESSION_SECRET'],

    // name of the session cookie
    name: 'userSession',

    // session expiration in ms
    duration: 24 * 60 * 60 * 1000,

    // session active duration in ms
    activeDuration: 1000 * 60 * 5,

    // array of user fields to expose in session object
    // id is already included
    expose: []

  },

  // Datastore "Kind" where user data is stored
  table: 'User',

  // Datastore namespace
  namespace: null,

  fields: {

    // name of the field that is used together with password during sign-in
    primary: 'username',

    // name of the field that stores the password
    password: 'password'

  },

  // array of headers that are sent in all responses
  // CORS and security headers should be included here, if your browser/client needs them
  headers: []

})

Authorizing other Google Functions

  1. Request the Session object from this library in your other Google Functions (i.e., API endpoints that require session credentials) and create an instance with the same options defined in the session section of the main session function;

  2. define environment variable GFA_SESSION_SECRET in your new function with the same value as the main session function;

  3. call authorize() on the session instance to validate it:

// Note the different class name and require path
const Session = require('@gfa/sessions-ds/session')

// Create and configure this object with the same options
//   as the "session" section of your /sessions function
const session = new Session({/*...*/})

// Entry Point
exports.handleRequest = function (req, res) {
  session.authorize(req, res, mainFunction)
}

function mainFunction (err, req, res, user) {
  if (err) {
    if (err.message === 'UNAUTHORIZED') {
      return res.status(401).end()
    }
    // handle other errors
    return res.status(500).end()
  }
  // rest of your code
  // `user` parameter contains exposed session data
}

License

MIT

About


Languages

Language:JavaScript 100.0%