MongoDB Atlas Custom JWT Authentication made Easy
LINKEDIN MICROSOFT DESIGNER

MongoDB Atlas Custom JWT Authentication made Easy

Step 1: Set Up AWS Cognito to Issue JWTs

Setting up AWS Cognito to issue JWTs involves creating and configuring a User Pool, setting up an App Client, and retrieving the JWKS URI for verifying the JWTs. Below are the detailed steps to achieve this:

Create a Cognito User Pool

1. Log into AWS Management Console:

- Navigate to the AWS Management Console at https://aws.amazon.com

- Sign in with your AWS credentials.

2. Open Amazon Cognito:

- In the AWS Management Console, type "Cognito" in the search bar and select Cognito from the search results.

3. Create a New User Pool:

- Click on Manage User Pools.

- Click on the Create a User Pool button.

4. Configure the User Pool:

Basic Settings: Provide a name for your User Pool and click Step through settings.

Attributes:

- Under Attributes settings, choose the standard and custom attributes you want to collect for your users. For example, you may choose attributes like email, phone_number, etc.

- You can also choose whether these attributes should be required during registration.

Policies:

- Define password policies for your users (e.g., password strength requirements).

MFA and Verifications:

- Configure Multi-Factor Authentication (MFA) if required. You can choose whether MFA is optional or mandatory and select the second factor (SMS, TOTP).

- Set up the email or phone verification method if needed.

Message Customizations:

- Customize the messages sent for verification, invitation, or password reset if required.

Tags: Optionally, add tags to your User Pool for easier identification and billing purposes.

Devices:

- Configure device tracking if you want to allow users to register their devices and provide additional security.

Triggers: (Optional)

- If you need to execute custom logic (like Lambda functions) during user sign-up, sign-in, or other events, configure triggers here.

5. Review and Create:

- After configuring all necessary settings, review your configurations.

- Click Create Pool.

2. Configure App Clients

1. Create an App Client:

- After creating your User Pool, you'll be prompted to configure an App Client.

- Navigate to App clients in the left-hand menu of your User Pool dashboard.

- Click on Add an app client.

2. Set App Client Name:

- Provide a name for your App Client (e.g., MyAppClient).

3. Configure OAuth Settings:

If you want to use OAuth 2.0 flows, ensure that Enable sign-in API for server-based authentication (ADMIN_NO_SRP_AUTH) is checked.

You can also enable other flows like Authorization code grant, Implicit grant, and Client credentials depending on your needs.

- Select the OAuth 2.0 scopes that your app will require. For example:

- openid: Required to obtain the ID token.

- email: Required if you want to access the user's email address.

- profile: Required to access profile information such as name and picture.

4. Set Token Expiration:

- Configure the access token, ID token, and refresh token expiration periods according to your application's requirements.

5. Create App Client:

- Click Create App Client to finish.

3. Retrieve the JWKS URI

1. Navigate to the User Pool General Settings:

- After creating the App Client, go to the General settings section of your User Pool.

2. Find the Pool ID and Region:

- Note down the User Pool ID and the AWS Region where your Cognito User Pool is hosted. You will need these to construct the JWKS URI.

3. Construct the JWKS URI:

- The JWKS URI is where you can retrieve the public keys used to verify JWTs issued by Cognito.

- The URI format is:


     https://cognito-idp.<Region>.amazonaws.com/<UserPoolID>/.well-known/jwks.json        

- Replace <Region> with your AWS region (e.g., us-east-1).

- Replace <UserPoolID> with your User Pool ID.

For example, if your User Pool is in the us-east-1 region and has an ID of us-east-1_12345abcde, your JWKS URI will be:

   https://cognito-idp.us-east-1.amazonaws.com/us-east-1_12345abcde/.well-known/jwks.json        

4. Test the JWKS URI:

- Paste the constructed JWKS URI into a browser or use a tool like curl to ensure it returns a JSON object containing your public keys. This file is used to verify the signatures of JWTs issued by Cognito.

Example output:

{         "keys": [                         
    { 
       "kid": "EXKID123",
       "alg": "RS256",
        "kty": "RSA",
        "e": "AQAB",
        "n": "EXAMPLEN1234567890",
        "use": "sig"
    },
]
}        

Now we move on to Step 2, Configuring Atlas:

After setting up AWS Cognito to issue JWTs, the next step is to configure MongoDB Atlas App Services to validate and authenticate users using these JWTs. Below are the detailed instructions for configuring Atlas to use JWTs issued by AWS Cognito.

1. Enable Custom JWT Authentication in Atlas

1. Access the Atlas App Services Dashboard:

- Log in to your MongoDB Atlas account at https://cloud.mongodb.com

- Select the project that contains your App Services app.

- Navigate to App Services by clicking on it in the left-hand menu.

2. Navigate to the Authentication Settings:

- In the App Services dashboard, click on Authentication from the left-hand menu.

- You will see several authentication providers listed, such as Email/Password, Google, etc.

3. Enable Custom JWT Authentication:

- Scroll down to find Custom JWT Authentication.

- Click on the EDIT button next to Custom JWT Authentication.

- Toggle the Provider Enabled switch to enable this authentication method.

2. Configure the JWT Validation Settings

Once Custom JWT Authentication is enabled, you need to configure Atlas to validate the JWTs issued by AWS Cognito.

1. Verification Method:

- Under the Verification Method section, choose Use a JWK URI. This tells Atlas to automatically validate the JWTs using the public keys provided by AWS Cognito.

2. Signing Algorithm:

- In the Signing Algorithm dropdown, select RS256.

- This matches the signing algorithm used by AWS Cognito to sign the JWTs. RS256 is an RSA signature with SHA-256.

3. JWKS URI:

- In the JWKS URI field, paste the JWKS URI that you obtained from AWS Cognito in Step 1.

- This URI points to the JSON Web Key Set (JWKS) that contains the public keys AWS Cognito uses to sign the JWTs.

Example format:

   https://cognito-idp.<Region>.amazonaws.com/<UserPoolID>/.well-known/jwks.json        

Replace <Region> and <UserPoolID> with your specific values from AWS Cognito.

3. Set Up Metadata (Optional but highly recommended)

If you need to extract additional information from the JWT or perform more granular validation, you can set up metadata fields within Atlas.

1. Add Metadata Fields:

- Under the Metadata Fields (Optional) section, click on + Add Field.

- You can specify fields in the JWT payload that Atlas should use for additional purposes. For example, you might want to use the sub (subject) claim as a user identifier or email for user-specific data.

- Key: sub

- Field Name: user_id (This could be mapped to a user ID in your application.)

2. Save Your Configuration:

- After configuring the necessary metadata fields, click Save to apply your settings.

4. Testing the Configuration

1. Generate a JWT from AWS Cognito:

- Test the configuration by generating a JWT using your AWS Cognito setup. This can be done by authenticating a user via the Cognito User Pool you created.

2. Authenticate Using the JWT:

- In your application, use the Realm SDK (e.g., React Native, Swift, etc.) to pass the JWT to Atlas App Services.

- The JWT should be automatically validated by Atlas using the JWKS URI you provided.

3. Verify Authentication:

- If configured correctly, Atlas will authenticate the user based on the JWT provided and grant access to your application’s services.

Example for Node.JS:

const jwt = "your_generated_jwt";  // JWT obtained from AWS Cognito after user login
const app = new Realm.App({ id: "your-realm-app-id" });
const credentials = Realm.Credentials.jwt(jwt);
try {
    const user = await app.logIn(credentials);
    console.log("Logged in as", user.id);
} catch (err) {
    console.error("Failed to log in", err);
}        

Step 3: Verify and Validate JWTs in Your Application

Once you've configured AWS Cognito to issue JWTs and MongoDB Atlas App Services to validate them, the next step is to integrate JWT verification and validation directly into your application. This step ensures that any JWTs used for authentication are valid, secure, and correctly processed.

1. Understanding the JWT Structure

A JSON Web Token (JWT) consists of three parts, each encoded in Base64URL:

1. Header:

- Contains metadata about the token, including the signing algorithm (alg) and the key ID (kid).

{
    "alg": "RS256",
    "kid": "abc123"
  }        


2. Payload:

- Contains the claims, which are statements about the user and additional data. These may include standard claims such as sub (subject), iat (issued at), exp (expiration time), aud (audience), and iss (issuer).

   {
    "sub": "1234567890",
    "name": "John Doe",
    "admin": true,
    "iat": 9876554433,
    "exp": 3333333333,
    "aud": "your_client_id",
    "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_example"
  }        

3. Signature:

- The signature is used to verify that the token has not been tampered with. It's created by encoding the header and payload using Base64URL and signing them with a private key using the specified algorithm.

for instance:

    HMACSHA256(
    base64UrlEncode(header) + "." + base64UrlEncode(payload),
    secret
  )
        


2. Token Validation

a. Verify the Signature:

- The JWT's signature ensures that the token hasn't been tampered with. The kid in the header is used to select the correct public key from the JWKS (JSON Web Key Set).

- To verify the signature, use the public key corresponding to the kid and apply the RS256 algorithm.

b. Check the Claims:

- Expiration (`exp`): Ensure the token hasn't expired by checking the exp claim against the current time.

- Audience (`aud`): Validate that the aud claim matches your app client ID.

- Issuer (`iss`): Ensure the iss claim matches the expected issuer, which is the URL of your Cognito User Pool (e.g., https://cognito-idp.us-east-1.amazonaws.com/us-east-1_example).

3. Using AWS Libraries for Validation

AWS provides several tools and libraries to simplify the JWT validation process. In a Node.js application, you can use the aws-jwt-verify library or other related tools to handle this process.

Example using jsonwebtoken and jwk-to-pem

const jwt = require('jsonwebtoken');
const jwkToPem = require('jwk-to-pem');
const jwksClient = require('jwks-rsa');
// Set up JWKS client
const client = jwksClient({
    jwksUri: 'https://cognito-idp.<Region>.amazonaws.com/<userPoolId>/.well-known/jwks.json'
});
// Function to get signing key
function getKey(header, callback) {
    client.getSigningKey(header.kid, function(err, key) {
        if (err) {
            callback(err);
            return;
        }
        const signingKey = key.publicKey || key.rsaPublicKey;
        callback(null, signingKey);
    });
}
const token = "your_jwt_token_here";
// Verify the JWT
jwt.verify(token, getKey, { algorithms: ['RS256'] }, function(err, decoded) {
    if (err) {
        console.error('JWT verification failed:', err);
    } else {
        console.log('JWT decoded successfully:', decoded);
    }
});        

Step 4: Integrate JWT Authentication into Your App

After setting up AWS Cognito to issue JWTs and configuring MongoDB Atlas App Services to validate them, the next step is to integrate this authentication mechanism directly into your client application. This allows your app to securely authenticate users using the JWTs issued by Cognito and validated by Atlas.

1. Passing JWT to Atlas

Once a user successfully authenticates via AWS Cognito, your application will receive a JWT that you can use to authenticate with MongoDB Atlas App Services.

Steps:

  1. Obtain the JWT: After the user logs in via Cognito, your app will receive the JWT, which can be used for further authentication requests.
  2. Pass JWT to Atlas: Use the MongoDB Realm SDK to send this JWT to Atlas App Services, which will validate it and authenticate the user.

Example using Realm SDK in JavaScript:

// Step 1: Obtain the JWT from AWS Cognito after user authentication
const jwt = "your_generated_jwt";  // JWT obtained from AWS Cognito

// Step 2: Initialize your Realm app with the specific Realm app ID
const app = new Realm.App({ id: "your-realm-app-id" });

// Step 3: Create Realm credentials using the JWT
const credentials = Realm.Credentials.jwt(jwt);

try {
    // Step 4: Log in to Atlas App Services using the JWT credentials
    const user = await app.logIn(credentials);
    console.log("Logged in as", user.id);
} catch (err) {
    // Step 5: Handle any errors that occur during login
    console.error("Failed to log in", err);
}
        

Explanation:

  • jwt: This variable contains the JWT that you received from AWS Cognito.
  • Realm.App: This initializes a connection to your MongoDB Realm app using the app ID.
  • Realm.Credentials.jwt: This creates credentials from the JWT, which are then used to log in the user.
  • app.logIn: This method attempts to authenticate the user with Atlas App Services using the JWT. If successful, the user is logged in and you can access the user object.

Step 5: Additional Integrations and Best Practices

To ensure that your JWT authentication system is robust, secure, and efficient, consider implementing additional integrations and adhering to best practices.

1. Caching Public Keys

Why:

  • Public keys from the JWKS endpoint are used to validate JWT signatures. Fetching these keys repeatedly from AWS Cognito can introduce latency and reduce performance.

How:

  • Implement a caching mechanism to store the public keys locally or in memory. This way, your application can validate JWTs quickly without needing to query the JWKS endpoint for each request.

Example:

  • You might cache the keys in memory with a time-to-live (TTL) to ensure they are periodically refreshed but not fetched on every single authentication attempt.

2. Handling Key Rotation

Why:

  • AWS Cognito periodically rotates the signing keys used to sign JWTs. If your application continues using an outdated key, JWT verification will fail.

How:

  • Monitor the kid (Key ID) field in the JWT header. If the kid does not match any cached key, refresh the cache by fetching the latest JWKS data from AWS Cognito.

Best Practice:

  • Implement a mechanism to check for key rotation, such as comparing the kid of the JWT with the keys in your cache. If a new key is detected, update your cache accordingly.

3. Security Best Practices

Validate All Claims:

  • Ensure that your application validates all relevant claims within the JWT, such as iss (issuer), aud (audience), exp(expiration), and sub (subject).

Proper Error Handling:

  • Implement robust error handling for JWT verification failures. If verification fails, deny access and log the error for further investigation.

Regular Security Reviews:

  • Regularly review and update your security configurations, including JWT handling mechanisms and key management policies.

Use Secure Storage:

  • Store sensitive information, like JWTs and API keys, securely within your application, ensuring they are protected from unauthorized access.


AND NOW

You're all done, this goes over the how's and why to setup and configure AWS with Atlas and eventually you're #MongoDB DEVICE Sync.

Brock Leonard

Mobile Application Developer focused on AI and Data solutions | Data Scientists| | Full-Stack Mobile App Developer

2 个月

Updated some things, the original formatting was for my blogger blog, and copy and pasted over here to LinkedIn.

要查看或添加评论,请登录

Brock Leonard的更多文章

社区洞察

其他会员也浏览了