jwtsurrealdb

IAM error when authenticating with token SurrealDB


I have recently added the --auth flag to make my instance of SurrealDB production ready as suggested in the documentation.

Upon doing so, my users can no longer view their data as this error is returned when authenticating with JWT tokens: {"code":403,"details":"Forbidden","description":"Not allowed to do this.","information":"There was a problem with the database: IAM error: Not enough permissions to perform this action"}

Removing the --auth flag allows this authentication, but this goes against the production ready recommendation.

SAMPLE JWT TOKEN CONTENT

{
  "ns": "Test",
  "db": "Test",
  "sc": "account",
  "tk": "user_tkn",
  "id": "users:test_user",
  "iat": 1703421361,
  "exp": 1703424961
}

SAMPLE REQUEST

curl -X POST "https://database.com/sql" \
     -H "Content-Type: text/plain" \
     -H "Accept: application/json" \
     -H "Token: <HS256 TOKEN HERE>" \
     -H "NS: Test" \
     -H "DB: Test" \
     -H "SC: account" \
     -d "SELECT * FROM users:⟨+44XXXXXXXXXX⟩"

For testing purposes, I have given PERMISSIONS FULL to the users table.

INFO FOR SCOPE

{
    "tokens": {
        "user_tkn": "DEFINE TOKEN user_tkn ON SCOPE account TYPE HS256 VALUE 'example123456'"
    }
}

Additional Info

Start Command: surreal start --auth --deny-guests --no-banner

Protocol: HTTPS

SurrealDB Version: 1.0.2 for linux on x86_64


Solution

  • You are correct that the --auth argument is indeed very recommended for production deployments and it is not necessarily to remove it to solve your problem. Your issue happens because you are providing the token in the Token header, whereas you should provide it in the Authorization header in the format Bearer $token. Assuming that the JWT is being constructed and signed correctly, this should solve your issue.

    Here is how I would reproduce what I understand is your intended use case:

    1. Start the server with surreal start --auth -u root -p root --deny-guests --no-banner. Remember to change the root credentials in your deployment.
    2. Connect to the server with surreal sql -u root -p root and run the following statements:
    use ns Test db Test;
    DEFINE SCOPE account;
    DEFINE TOKEN user_tkn ON SCOPE account TYPE HS256 VALUE 'example123456';
    DEFINE TABLE users PERMISSIONS FULL; -- Remember to properly restrict this.
    CREATE users:test_user CONTENT {"exists": true};
    
    1. Create a token (e.g. in jwt.io) with the HS256 algorithm and using example123456 as the signature secret. Do not check the box to encode the secret. The token payload should contain the following:
    {
      "ns": "Test",
      "db": "Test",
      "sc": "account",
      "tk": "user_tkn",
      "id": "users:test_user",
      "iat": 1703421361,
      "exp": 1803424961
    }
    
    1. Assuming that you are running SurrealDB locally as I described, you can then execute queries using the token that you just generated with HTTP requests like the one generated by the following command:
    curl -vvv localhost:8000/sql \
    --data "SELECT * from users:test_user" \
    -H "Accept: application/json" \
    -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJucyI6IlRlc3QiLCJkYiI6IlRlc3QiLCJzYyI6ImFjY291bnQiLCJ0ayI6InVzZXJfdGtuIiwiaWQiOiJ1c2Vyczp0ZXN0X3VzZXIiLCJpYXQiOjE3MDM0MjEzNjEsImV4cCI6MTgwMzQyNDk2MX0.SsuApbUvBxsOvO8T5nvtJ294bsUbdynits77dgiETT8"
    

    Following the instructions above, you should get the following response:

    [{"result":[{"exists":true,"id":"users:test_user"}],"status":"OK","time":"97.48µs"}]
    

    I hope this was helpful! Feel free to let me know if you need any other help.

    PS: I work in SurrealDB.