Coder Social home page Coder Social logo

cognito-srp's Introduction

# cognito-srp

Secure Remote Password protocol implementation compatible with Amazon Cognito.

This package borrows heavily from the srp-js package, but implements a slight variant of the protocol in order to work with Amazon Cognito. Also inspired by bits from amazon-cognito-identity-js, the official client library.

Use it if you want to interact with Cognito without all the bloat of the AWS SDK, or if you want to write a server that acts like Cognito, and is therefore compatible with the AWS SDK. Alternatively, use simply as a replacement for srp-js.

Usage

First, install:

yarn add cognito-srp

Then import. Your starting point will usually be the UserPool class:

import { UserPool } from 'cognito-srp';

Instantiate a pool, using your pool name:

const userPool = new UserPool('7DZy4Fkn7');

Note that the pool name here is not the full UserPoolId that the AWS SDK asks for, i.e.:

const UserPoolId = 'us-east-2_7DZy4Fkn7';
const poolname = UserPoolId.split('_')[1];

Then the usage differs depending on whether you want to use it on the client or server.

On the server

Before you can check the identity of users, you need to create at least one:

const user = await userPool.createUser({username: 'testuser', password: 'pass123'});

The user object contains the username, a salt, and a verifier value, a long string of hex which can be thought of as a password hash.

When checking the identity of a user, the client will first make a request, passing the username and a generated key called A.

Assuming you can find the user from the username, you can then ask for a password challenge:

const challenge = await userPool.getServerChallenge(user);

From the challenge, you can get the server's generated key, called B, to pass back to the client.

const B = challenge.calculateB();

You can also start a session, passing the client's key, A:

const session = challenge.getSession(A);

The server sends B back to the client, along with their salt and a base64-encoded "secret block". I'm not completely sure what that block is for, perhaps session management.

Then the client will make another request with a password signature, the secret block, and a timestamp. To verify that they have the correct password, you must also calculate the signature and compare the two. If they match, the client has the correct password.

const signature = session.calculateSignature(secretBlock, timestamp);

if (signature === requestSignature) {
  // yay
}

If you need to bin the session and rehydrate it later, for example, between the two requests, you can recreate it from the "HKDF" value:

const hkdf = session.getHkdf();

// ...

const newSession = new Session(poolname, username, hkdf);

Note that knowing the HKDF is as good as knowing the password for this session, so keep it safe if you're writing something important.

If you're writing a mock server to test something that uses cognito, you could send the HKDF out as the "secret block", as the client will echo it back to you on the next request, and it saves trying to store it.

This is obviously not a good idea in production.

On the client

Once the user has entered their username and password, you can create a challenge:

const challenge = await userPool.getClientChallenge({username, password});

You can then make a request to the server with the user's username and a client key (A):

const A = challenge.calculateA();

The server will respond with the server key (B), the user's salt, and a secret block. The client can then create a session:

const session = challenge.getSession(B, salt);

Then, the client can calculate the signature as proof that it knows the password:

const timestamp = getTimestamp();
const signature = session.calculateSignature(secretBlock, timestamp);

The client sends the secret block, timestamp and signature back to the server, and its identity is established.

Notes

The exact format of the requests and responses to Amazon Cognito is outside the scope of this package – it only implements the SRP stuff, and you can wrap it in whatever protocol you want.

Although this library is compatible with Cognito and therefore successfully implements the Secure Remote Password protocol, I'm not a security expert, and I don't claim to understand the maths behind it – keep that in mind before you use it for something important.

cognito-srp's People

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.