Third Party Auth with SurrealDB (like Firebase , Auth0, Clerk or Home Grown JWT system)

166 Views Asked by At

Is there a way to implement third party auth with surrealdb and run authorization logic accoridng to the JWT tokens returned from the third party auth service. In my case it is a home grown auth solution which uses JWTs for authentication i like to use these JWTs with surrealdb.

I just started with surrealdb implementing a data aggragation system for realtime data viz with surrealdb live queries

3

There are 3 best solutions below

0
Obinna Ekwuno On

You can implement basic Auth with GitHub for example :

DEFINE SCOPE account SESSION 1d SIGNIN {
    LET $userToken = http::post('https://github.com/login/oauth/access_token', {
        "client_id": "GITHUB_CLIENT_ID",
        "client_secret": "GITHUB_SECRET_ID",
        "code": $code
    }, {
        "Accept": "application/vnd.github+json",
    });

    LET $userInfo = http::get('https://api.github.com/user', {
        "Accept": "application/vnd.github+json",
        "Authorization": string::concat("Bearer ", $userToken.access_token)
    });

    LET $userID = type::thing("users", ['github', $userInfo.type, $userInfo.id ]);

    LET $user = SELECT * FROM $userID;

    IF $user[0].id == NONE THEN 
        CREATE $userID CONTENT {
            name: $userInfo.name,
            avatar_url: $userInfo.avatar_url,
            profil_url: $userInfo.html_url
        }
    ELSE IF 
        [$user[0].name, $user[0].avatar_url, $user[0].profil_url] != 
        [$userInfo.name, $userInfo.avatar_url, $userInfo.html_url] THEN
        UPDATE $userID SET 
            name = $userInfo.name, 
            avatar_url = $userInfo.avatar_url, 
            profil_url = $userInfo.html_url;
    ELSE
        RETURN $user[0];
    END;

    RETURN (SELECT * FROM $userID)[0];
}

Gotten from Discord. Currently SurrealDB does not officially support third party Auth but it is possible.

Use like so :

db.signin({ NS: 'test', DB: 'test', SC: 'account', code, })

0
Alex On

You could integrate manually with a third party authentication provider in some way and use SurrealDB's scoped users feature.

Here's a basic way with Google where you could use the unique sub property from the Google profile info (in this example using the SurrealDB JavaScript SDK). There is probably a better, more secure way of doing this but it's good enough for demonstration I think:

// verify the Google authentication and get the profile info in some way e.g. with https://cloud.google.com/nodejs/docs/reference/google-auth-library/latest or from the token set by your provider

try {
  await db.signin({
    namespace,
    database,
    scope: 'users',
    sub: profile.sub,
    email: profile.email
  })
} catch {
  await db.signup({
    namespace,
    database,
    scope: 'users',
    sub: profile.sub,
    name: profile.name,
    email: profile.email
  })
}

For the schema you could use:

DEFINE TABLE users SCHEMAFULL
    PERMISSIONS
        FOR select, update, delete WHERE id = $auth.id;

DEFINE FIELD sub ON users TYPE string;
DEFINE FIELD name ON users TYPE string;
DEFINE FIELD email ON users TYPE string ASSERT string::is::email($value);

DEFINE INDEX sub ON users COLUMNS sub UNIQUE;
DEFINE INDEX email ON users FIELDS email UNIQUE;

DEFINE SCOPE users
  SESSION 1d
  SIGNUP (CREATE users SET sub = $sub, email = $email, name = $name)
  SIGNIN (SELECT * FROM users WHERE sub = $sub AND email = $email)
;

So users authenticate and then you'll separately create a record in the users table. Here you could apply any permissions, types or checks on each field you want to use.

0
Gerard On

There is now an official guide on how to authenticate with SurrealDB using Auth0 in the SurrealDB documentation. The guide can also be useful as a reference for how to leverage other third-party JWT to authenticate with SurrealDB, specially in a custom solution like yours where you have control over the claims included in the token. I hope this is useful!

PS: I work in SurrealDB.