How to Integrate custom JWT as Auth method for Atlas Device Sync

Im trying to connect my existing backend JWT (Laravel Sanctum) to a new Atlas Sync app.
My app works entirely with the JWT right now but i am trying to use the Custom JWT from atlas. Im not sure how to connect it.
In the settings I do not see a way to specify my server URL or the JWT generation URI.
In the docs you can see the user passes the credentials to the Realm App, in my case this s phone number and a one time code. Then realm Forwards credentials… but since i cant set up the URL how do i know where realm is sending these credentials ?
What am I missing here?

I’m mind blown this has been viewed 1,000 times and not even been attempted to be answered. I’m sorry I didn’t even see this the last time I was even going through these forums.

Hi Luis, it may be too late for you at this point but I am answering this for everyone else as a former TSE I used to build custom JWTs for customers and troubleshooted them.

You don’t need to specify your server URL or JWT generation URI in Atlas App Services. Instead, focus on configuring the Custom JWT authentication in Atlas to validate the JWTs issued by your Laravel Sanctum backend. The Realm SDK handles the transmission of the JWT to Atlas, where it is validated based on the settings you’ve configured.

Unless MongoDB training for TSEs have failed me, this is how it worked for the couple of years I worked for MongoDB:

JWT Issuance on Your Backend: When a user logs in to your app (using phone number and one-time code), backend issues a JWT.

Passing JWT to Atlas: Your client app (i.e. mobile or web) then takes this JWT and passes it to Atlas App Services via the Realm SDK.

JWT Validation: Atlas App Services validates the JWT. You don’t need to specify your server URL or JWT generation URI in Atlas. Instead, you configure Atlas to either manually validate the JWT using a signing key, or validate it using a JWKS if provided by the third-party system.

Now, be sure to:
Enable Custom JWT Authentication
In the App Services UI, go to Authentication > Custom JWT Authentication and enable it.

Manually Specify Signing Keys
Set it to HS256 like shown in your photo.
Add the signing key generated by sanctum.

JavaScript code example for your app (do debug but this is the general direction you’re looking for off hand):

const jwt = "your_generated_jwt";  // **This JWT comes from your Laravel backend**
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);
}

Let Atlas use the JWT to authenticate the user based on the manually signed keys.

When your users log in using the Realm SDK and provide the JWT, Atlas App Services directly validates the JWT against the signed keys.

There’s no need to worry about Atlas forwarding the credentials somewhere else; it’s all handled internally based on the JWT’s content and signature verification.

I hope this helps you going forward, and others who come across this issue and the overly complicated explanations in documentation. I hope this simplifies the Custom JWT processes, as it’s very easy to see reading the documents to feel overwhelmed on an incredibly simple process (by design, I actually feel the JWT process initiated by Atlas is a lot more simple than even they try to advertise, and I have no idea why they make it sound so complicated.)

Also, specifically to Laravel Sanctum, you might rather want to use Laravel Passport instead, as that is directly made for JWT authentication specifically. The difference is yes, Sanctum is token based, but Passport is immediately made exclusively (well mostly, almost nearly exclusive) for JWT authentications.

For that simply look up Passports JWT documentation for it issuing JWT, and you can either use MongoDB’s provided Realm code for JWT auth, or you go by what I posted above and change it to your needs, either way that’s the direction you want to go for simplifying JWT Custom Authentication.

If you’d like a simple GitHub link to a realm app I made about 2 years ago using Custom JWTs and even Google or Apple Auth, let me know. I have a working example for Passport (although 2 years old and unknown if it’s deprecated or not) and I have working examples using AWS JWT Issued tokens with AWS Firehose pumping wildfire data to a demo app.

If you’d like access to them, just message me your GitHub and I’ll send you an invite to them for review if it helps you launch your app.

If you want to see how to do this with AWS Cognito, here’s a guide I just published:

@Luis_Perez1

Got your initial issue resolved, this is how you do this using Sanctum. It’s been tested and verified by 3 separate people so this is at least one exact way of doing this.

Step 1: Set Up Laravel Sanctum to Issue JWTs

  1. Install Laravel Sanctum: Ensure Laravel Sanctum is installed and configured in your Laravel project. You can install it using Composer:

composer require laravel/sanctum

  1. Configure Sanctum: Run the following command to publish the Sanctum configuration file:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

Then, migrate the Sanctum tables:

php artisan migrate`

  1. Use Sanctum for API Token Authentication: Add the HasApiTokens trait to your User model to enable token creation:
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
}
  1. Create JWT Tokens: You need to generate JWT tokens for authenticated users. You can use the createTokenmethod to issue a JWT with specific abilities (scopes):
use Illuminate\Http\Request;

Route::post('/tokens/create', function (Request $request) {
    $token = $request->user()->createToken('API Token', ['*']);

    return response()->json([
        'token' => $token->plainTextToken,
    ]);
});
  1. Customize the JWT Payload (Optional): You may customize the JWT payload by extending the PersonalAccessToken model and modifying the token’s creation process.

Step 2: Configure MongoDB Atlas to Accept JWTs

  1. Enable Custom JWT Authentication in Atlas: Go to the Atlas App Services dashboard, and navigate to the Authentication section. Enable Custom JWT Authentication.
  2. Configure JWT Validation Settings:
  • Verification Method: Use the JWKS URI provided by your Laravel application or JWT provider.
  • Signing Algorithm: Select HS256 or another algorithm supported by Laravel Sanctum.
  • JWKS URI: Provide the endpoint for the public keys that Atlas can use to validate the JWTs.
  1. Set Up Metadata (Optional): Configure metadata fields within the JWT that Atlas should use for additional validation or data extraction. For instance, the JWT payload might include claims like sub (subject, typically the user ID), exp (expiration time), and custom claims like roles or permissions.

Step 3: Verify JWTs in Laravel

  1. Middleware for JWT Authentication: Create middleware in Laravel to parse and verify JWTs in incoming requests:
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class AuthenticateWithJwt
{
    public function handle($request, Closure $next)
    {
        $token = $request->bearerToken();

        if (!$token) {
            return response()->json(['error' => 'Token not provided.'], 401);
        }

        try {
            $decoded = JWT::decode($token, new Key(env('JWT_SECRET'), 'HS256'));
            $request->auth = $decoded;
        } catch (\Exception $e) {
            return response()->json(['error' => 'Invalid token.'], 401);
        }

        return $next($request);
    }
}

Register this middleware in Kernel.php:

protected $routeMiddleware = [
    'auth.jwt' => \App\Http\Middleware\AuthenticateWithJwt::class,
];
  1. Protect Routes: Protect routes using the JWT authentication middleware:
Route::middleware('auth.jwt')->get('/user', function (Request $request) {
    return $request->user();
});

Step 4: Integrate JWT Authentication with Atlas

  1. Pass JWT to Atlas: In your client application, after the user authenticates via Laravel Sanctum, obtain the JWT and pass it to MongoDB Atlas for user authentication via Realm SDK or HTTP requests.Example using Laravel’s HTTP client:
$response = Http::withToken($jwtToken)->get('https://realm.mongodb.com/api/client/v2.0/app/YOUR_APP_ID/auth/providers/custom-token/login', [
    'access_token' => $jwtToken,
]);

$user = $response->json();
  1. Validate JWT on Atlas: Atlas will validate the JWT based on the configuration settings you provided (JWKS URI, algorithm, etc.). If the JWT is valid, Atlas will allow access to the requested resources.

A year later, but it’s figured out for you if you ever come across this problem again.

This issue has kind of hit me a bit hard, as it’s something that really shouldn’t be so hard to explain for general consumers using these products to be able to adapt and use their services.

Hope this helps whoever.

I’ll also be posting this on my LinkedIn and in my blog as well.