Giter Club home page Giter Club logo

Saaslify

How to use the SDK?

We will just touch JavaScript Client SDK and NodeJS

import { Saaslify } from '/saaslify'
const saaslify = Saaslify({ saasId: 'your-awesome-app' })
...

or use our CDN

const script = document.createElement('script')
script.src = "https://unpkg.com/saaslify"
script.async = true
script.onload = () => {
    const saaslify = window.Saaslify({ saasId: 'your-awesome-app' })
    ...
}
document.head.appendChild(script)

More efficient use of CDN

Authentication - Who am I?

Recipe 1 - Login Button

We assume you have a button some where

<span id="login" data-provider="" data-scopes="">login with github</span>
document.querySelector(`#login`).addEventListener('click', async (e) => {
    const loginURL = await saalify.user.getLoginUrl({
        provider: e.target.dataset['provider'],
        scopes: e.target.dataset['scopes'].split(';'),
        callbackURL: document.location.href // redirect to this page again
    })

    window.location.href === loginURL
})

Recipe 2 - Check whether is loggedin

const user = await saalify.user.getUser({
    provider: e.target.dataset['provider'],
    scopes: e.target.dataset['scopes'].split(';')
})

const isLoggedIn = Boolean(user)

Recipe 3 - Automatic redirect if not loggedin

const user = await Saalify.user.getUser()

const isLoggedIn = Boolean(user)

if (!isLoggedIn) {
    const loginURL = await Saalify.user.getLoginUrl({
        provider: e.target.dataset['provider'],
        scopes: e.target.dataset['scopes'].split(';')
    })

    window.location.replace(loginURL) // `replace` overwrites the browser history
}

Authorization - What can I access?

Pure frontend applications

const user = await saalify.user.getUser()

Returns


Recipe for mixed frontend and backend authorization

In your browser

const body = {
    bananas: 5
}

Saalify.user.fetch(`https://your.api-endpoint.com/order`, {
    method: 'POST',
    body: body, // remark *
    headers: {
        'content-type': 'application/json',
        'accept': 'application/json'
    }
})

Our fetch method differs from the normal in that we transform the body and add an additional field.

{
    "jwt": "...",
    "bananas": 5
}

Here is an example of a receiving node js server:

import * as express from 'express'

const app = express();

app.use(express.json());

app.post('/order', async (request, response) => {
    const { jwt, bananas } = request

    try {
        const userData = await saaslify.user.jwtVerify(jwt)

        const bananaPlan = userData.products.find(x => x.plan.name === 'banana')

        if (bananaPlan) {
            // ... order 5 bananas
            response.status(201).json({ data })
            return
        } else {
            response.status(201).json({ error: `User ${jwt.userId} has no plan "banana".` })
            return
        }
    } catch (e) {
        response.status(401).json({ error: e.message })
        return
    }
})

app.listen(3000, () => {
    console.log(`Server is listening at port 3000`)
})

Other server side programming language

The only part which we have to use Saaslify library is:

await Saaslify.jwtVerify(jwt)

Recipe for machine to machine authorization

For cli or server to server applications, you will need some sort of api keys.

Either use our custom user management to allow users to generate machine tokens or build your own frontend with our Client SDK. User need to be logged in for this.

const token = await Saaslify.user.generateMachineToken({ name: 'terminator' })

Machines fetch just like browsers:

const machine = Saaslify.auth({ token, name, userId })

machine.fetch(`https://your.api-endpoint.com/order`, {
    method: 'POST',
    body: body, // remark *
    headers: {
        'content-type': 'application/json',
        'accept': 'application/json'
    }
})

You can double check on the server whether it is a machine jwt you are communicating with

const machineName = await Saaslify.user.jwtVerify(jwt).then(x => x.machine?.name)

const isMachine = Boolean(machineName)

Remarks: Security & limitations

Other Backend langueges

For other programming language, we you can simply request a JWT

curl https://auth-(dev|prod).saaslify.io/${saas_provider}/user/${user_id}/machine/${name}
    -X GET
    -H "X-SAASLIFY-MACHINE_AUTH: ${token}"
{
    "jwt": "..."
}

Send your requests against the real server and verify them against the following public keys

curl https://auth-(dev|prod).saaslify.io/${saas_provider}/.wellknown
    -X GET
    -H "X-SAASLIFY-MACHINE_AUTH: ${token}"
[{
    "privateKeyId": "...",
    "timestamp": 0,
    "publicKey": ""
}]

Please check the library section of jwt.io.

If you have a working solution in another language, please make a PR.

Key rotations

We rotate keys on a regular bases. Keys which should be active can be found here

Never persist the JWT

The client SDK hides away the jwt away. It is only safe to keep them in memory.

Custom fetch

The body in the fetch method is enriched with jwt, potentially overwriting an existing field. Also the body is required to be an object. This is necessary, because our JWT can exceed the size of accept headers because we don't want to limit the number of products your customer has access to.

Caching

The SDK has some build in memory caching. On the server, you might want to tune performance by shipping your own redis caching.

Contributing

Join the community

Make a PR

Build your own SAAS

Implement a feature

Make a donation for a feature to be implemented

saaslify's Projects

aws-auto-cleanup icon aws-auto-cleanup

Open source application to programmatically clean your AWS resources based on a whitelist and time to live (TTL) settings

feathers icon feathers

A framework for real-time applications and REST APIs with JavaScript and TypeScript

hello-world icon hello-world

This is a hello world application how to integration with saaslify

serverless-apigw-sqs-plugin icon serverless-apigw-sqs-plugin

A Serverless plugin that creates an AWS API Gateway resource to connect to an AWS Simple Queue Service (SQS) without the use of a lambda. Without the use of this plugin, any interactions with the queue through public network will need to go through a proxy lambda.

subzero-cli icon subzero-cli

Tooling to aid development of subZero/PostgREST based backend APIs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.