MongoDB Atlas Custom JWT Authentication made Easy
Brock Leonard
Mobile Application Developer focused on AI and Data solutions | Data Scientists| | Full-Stack Mobile App Developer
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:
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:
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:
How:
Example:
2. Handling Key Rotation
Why:
How:
Best Practice:
3. Security Best Practices
Validate All Claims:
Proper Error Handling:
Regular Security Reviews:
Use Secure Storage:
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.
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.