DEV Community

David Israel for Uclusion

Posted on • Updated on

CircleCI, AWS Cognito, Amplify and Github Login

Uclusion is built on a relatively pure AWS stack and uses Cognito and Amplify Auth for user authentication.

If you are too, and want to enable login with GitHub here’s how you do it.

Step 1: Bridge OpenID Connect and Github Oauth2.

Unfortunately, Cognito and GitHub can’t directly talk with each other because Cognito supports SAML and OIDC while GitHub only supports Oauth. Fortunately, there exists an open source shim, the GitHub OpenID Connect Wrapper for Cognito that bridges the Gap.

The wrapper has two basic modes of operation, as a lambda with API gateway, and as a standalone node instance. We’re Lambda based ourselves, so we went with that option. The of the Wrapper does a good job of describing the setup steps for Cognito and here are the instructions for creating an Oauth app in Github, so I’ll just be focusing on how to get the shim working with CircleCI and Amplify.

Step 2: Create a CircleCI config.

Since we use CircleCI we needed a way to deploy the lambda along side our existing Serverless Framework based stacks, even though the Wrapper uses aws cli and aws sam. It turns out that’s not to hard with a good CircleCI config.yml.Here’s ours:

version: 2
      - image: circleci/python:3.7.2

    working_directory: ~/repo

      - checkout
      - run:
          name: get node repo
          command: wget -qO- | sudo -E bash -
      - run:
          name: install node
          command: sudo apt-get install -y nodejs
      - run:
          name: Get aws cli
          command: sudo pip install awscli
      - run:
          name: Get aws sam
          command: sudo pip install aws-sam-cli
      - run:
          name: Setup config
          command: cp $
      - run:
          name: Install NPM deps
          command: npm install
      - run:
          name: Deploy
          command: npm run deploy

  version: 2
      - build:
              only: /^dev_backend.*/
              ignore: /.*/
          context: dev
Enter fullscreen mode Exit fullscreen mode

The file basically sets up node, cli and sam, and makes use of CircleCI Environment Variables to establish our AWS credentials, to specify which version of the env name we’re deploying (dev, stage, production), and to set up auto workflow (in this case just dev) so we can auto deploy when we do releases with the tags dev_backend.

To use this file, fork the Wrapper’s repo, and create the file .circleci/config.yml inside the root of the new repo. Then go into CircleCI and tell it to monitor the project. If you haven’t configured your CircleCI to automatically respond to GitHub events the directions are here:

Step 3: Tell Amplify to log in with your new provider:

When you setup the OIDC source in Cognito according to the directions in the wrapper, you gave the integration a name. Lets assume that name was ‘GithubLogin’.

If you’ve already configured Amplify for federated login with Google or Facebook (which you really should do unless you have a good reason not to), then Amplify makes using your new provider really easy. All you have to do is change the ‘provider’ flag when doing federated logins to ‘GithubLogin’.

<Button onClick={() => Auth.federatedSignIn({provider: 'GithubLogin'})}>Github Login</Button>
Enter fullscreen mode Exit fullscreen mode

You’ll want to style that and make it fancier of course, but that’s all it takes. Assuming everything has been set up correctly you can now log in with Github Identities.

Things I haven’t told you:

  1. Custom Domains: You should really have a custom domain for your Cognito Pool and your API gateway, as things will look much more professional. Instructions for Cognito are here, and for API gateway are here.

  2. Post login workflows: You’ll probably want to do something fancy with the GitHub users so make sure to inspect the Amplify user attributes on your pages, as Cognito will helpfully tell you that the user came from ‘GithubLogin’. The attributes can be gotten via code like this:

    .then((user) => {
    const { attributes } = user;

See the Javascript in production code here.

Top comments (2)

davidwells profile image
David Wells

Hey! Great post!

Quick question, is this login flow going through the hosted UI or happening all in your app via amplify + the federatedSignIn call you described.


davidwells profile image
David Wells

Aha found it at

No hosted UI! Very nice work!