Skip to content

AWS Cognito User Pool custom authentication with go lang

Notifications You must be signed in to change notification settings

thanhchungbtc/go-cognito-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Example of using AWS Cognito with custom authentication

Prerequisite

  • Create user pool in AWS Cognito
    • Do not check generate secret key
    • Create an app client
    • Enable verification method of your choice. We'll be using email in this example

Features

Login

User can authenticate with username and password using USER_PASSWORD_AUTH flow, or by refresh token using REFRESH_TOKEN_AUTH.

Example response

{
  "access_token": "...",
  "expires_in": 3600,
  "id_token": "...",
  "refresh_token": "...",
  "token_type": "Bearer"
}

Register & verification

Vertification code will be sent as of the method you choose when create user pool

Refresh token

To access protected resources, send the request along with Authorization header. You'll get 401 when the token is expired, in that case just reauthenticate with the refresh_token

axios.get("/api/me", {
  headers: { Authorization: `Bearer ${obj.id_token}` },
});

To automate this process, we'll create an interceptor.

const createInterceptor = () => {
  const interceptor = axios.interceptors.response.use(
    (res) => res,
    (err) => {
      // not an unauthorized request, continue with error
      if (err.response.status !== 401) {
        return Promise.reject(err);
      }

      // get refresh token
      const data = window.localStorage.getItem("auth");
      const obj = JSON.parse(data);
      const { refresh_token } = obj;
      if (!data) {
        return Promise.reject(err);
      }
      // eject interceptor to prevent loop in case refresh token itself returns 401
      axios.interceptors.response.eject(interceptor);
      return axios
        .post("/api/login", {
          refresh_token,
        })
        .then(({ data }) => {
          // update the authenticated token
          window.localStorage.setItem("auth", JSON.stringify(data));
        })
        .catch((err) => {
          // remove the invalid authorization info
          window.localStorage.removeItem("auth");
          return Promise.reject(err);
        })
        .finally(createInterceptor);
    }
  );
};

Parse the jwt using public key

When creating an user pool, the public keys will be available at https://cognito-idp.{region}.amazonaws.com/{user_pool_id}/.well-known/jwks.json

Find the public key that matches kid in the JWT's header. Leverage the existing jwt library, the parsing is simple as

jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
  kid := token.Header["kid"].(string)
  jsonWebKey := a.keys.LookupKeyID(kid)[0]

  publicKey := &rsa.PublicKey{}

  if err := jsonWebKey.Raw(publicKey); err != nil {
    return nil, err
  }
  return publicKey, nil
})

About

AWS Cognito User Pool custom authentication with go lang

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published