User Management
This section details how user accounts can be created and managed.
Each user account is required to be assigned an email address as well as a username. The email address is needed for authentication and sending API notifications while the username is used by applications and API internals to manage data ownership. This makes it possible for users to change their email address without affecting existing data and apps configuration.
Note
As a convenience, email addresses may be stored in the TOML settings file to then login with the username on the command line.
Each user account needs to be verified to gain full access of the available
features. This should be done via email verification with a unique link. If
SMTP is not configured for the API instance, it can be done via the
renelick-admin command line utility invoked from within the API service
container to directly update the database entry.
When a user account needs to be closed, rather than deleting it which would in
principle require all its related data to be deleted too, a standard practice
is to deactivate the account instead. This can be done with the
renelick-admin tool in a similar way, to unset the is_active flag.
Some users can be granted additional permissions and become "superusers". This is for example required to perform some maintenance tasks such as updating accounts and data that belongs to another user. There should typically be at least one superuser created when the API instance is initially deployed.
Standard Authentication
To register a new user, an email address and username need to be provided:
On private instances, registering new users typically requires a superuser or
"admin" to run this command. That's when the ADMIN_REGISTER environment
variable is set to true in the API service, which is the default. To disable
it, add ADMIN_REGISTER=false to the .env file and restart the API service.
This is needed initially to create the first superuser. Then to register a new
regular user with the flag enabled again, first login with the superuser
account and then pass its name to the --admin argument:
For example, to register a user bob and if the superuser is admin:
Login
Once a user has been registered, it's time to login:
This command creates a JWT token which will be valid for an hour. Once expired, you will need to login again (until refresh tokens are supported by the API).
To check whether you're currently logged in:
$ renelick whoami
JWT expires in 59 minutes.
Connecting to http://172.17.0.1:8000
User profile:
id 67881592413337823cc732c3
username bob
email bob@example.com
full_name
is_superuser False
is_verified False
Verification
This is when users would need to be verified, to confirm their email address is correct and avoid fake user accounts. Now we know the unique id for the user that was just created, we can run this command:
Going Further
If you also wanted to give superuser permissions to a user account:
Note
See also the Quick-Start Guide about how to set up a new instance from scratch.
In some cases, the credentials have to last longer than an hour. For example, thiw would be the case with services that aren't run interactively but need to be always connected to the API. It's possible to get a persistent API key when logging in instead of a temporary JWT as shown below:
Finally, to avoid having to pass the username on the command line all the time,
a default one may be found in settings.toml either explicitly in the
[default] section or by looking up the first user listed for the matching API
instance. The settings.toml file will be updated automatically when
registering new users or when logging in.
OAuth2 Authentication
It's also possible to login using third-party credential providers via OAuth2. Support has been implemented at the API level for Google authentication but not in the reference web frontend or command line tools yet. So it can be used but currently requires some manual steps. If there is already an existing Renelick user account with the same email address as the Google account then it will be reused by storing some Google information in the Renelick database.
Google OAuth2 Configuration
Note
Google authentication requires going through a verification procedure for a full production deployment, otherwise the number of users is limited to 100. This is not detailed here.
The first step is to enable the People API in GCP. To do this, you'll need to create a Google Cloud account if you don't already have one. Then visit the People API page and enable it.
Next, an OAuth2 client entry needs to be set up in GCP for your API instance. This can be done on the clients page by providing the following values:
- Application Type: Web application
- Name: Arbitrary Renelick deployment name
- Authorized redirect URIs:
https://renelick-url/v0.14/auth/google/callback
Adjust the redirect URI with your own deployment domain name, port number etc.
To try OAuth2 with a local deployment, provide this default URI:
http://127.0.0.1:8000/v0.14/auth/google/callback
Note
The Renelick API version v0.14 is hard-coded in this example. Using
latest should work too but is not fully tested yet.
Once the OAuth2 client has been created, an ID and secret will be provided.
Add them to your API deployment's .env file as follows:
It's also necessary to generate a random OAuth2 local secret which will be used when generating the tokens:
Make sure the API service is restarted in order to load these new environment variables. You should see this message in the API log:
Then go to the scopes page and add the following items:
./auth/userinfo.email./auth/userinfo.profileopenid
This will make it possible for Google user accounts to share their email address and profile data with the Renelick API to store it alongside their local user accounts. In particular, the email address is used to link any existing Renelick user account with a matching Google one.
Manual Login
Frontend Integration
This is where the web frontend integration is currently missing, to provide an option to login with a Google account on the login page and then store the JWT in the session to access the Renelick API via the web frontend directly in the browser. Some follow-up improvements could also be done to facilitate this with CLI tools.
The first step is to get a Google login URL via the authorize endpoint. In
the example below, we're using the default docker-compose local deployment
but this should work with any public one too:
$ curl http://127.17.0.1:8000/latest/auth/google/authorize
{"authorization_url":"https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=<CLIENT-ID>&redirect_uri=http%3A%2F%2F127.17.0.1%3A8000%2Fv0.14%2Fauth%2Fgoogle%2Fcallback&state=<STATE>&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email"}
The CLIENT-ID and STATE values have been removed from the example above,
but they should be long random strings. The CLIENT-ID value should match the
client ID stored earlier in the .env file. Note that the callback URL here
does contain the exact Renelick API version v0.14 which is why it was
explicitly mentioned in the setup instructions. This may be adjusted to use
latest instead.
The next step is to open this unique URL as-is in a web browser and follow the instructions. Once logged in with the Google account, the browser will send a request to the callback URL with a JWT token and the user account information. If this is all done correctly, the Renelick API will accept the request and store the OAuth2 credential within any exisinting user account with a matching email address. It will then return the JWT which will appear as raw JSON in the browser window:
The actual JWT value can then be stored manually in the
~/.config/renelick/credentials.json file and used to access the API.
To check whether it's working as expected, here with a gtucker user:
$ renelick whoami
JWT expires in 54 minutes.
Connecting to http://172.17.0.1:8000
User profile:
id 678788e8d5a0ff2512f495cd
username gtucker
email gtucker@gtucker.io
full_name
is_superuser False
is_verified False
The Renelick user entry in the database should now also contain the OAuth2 account details since they both have the same email address:
$ docker-compose exec mongo mongosh renelick
[...]
renelick> db.user.findOne({username: 'gtucker'})
{
_id: ObjectId('678788e8d5a0ff2512f495cd'),
username: 'gtucker',
full_name: null,
email: 'gtucker@gtucker.io',
hashed_password: '<HASHED_PASSWORD>',
is_active: true,
is_superuser: false,
is_verified: false,
oauth_accounts: [
{
id: ObjectId('678814ae413337823cc732c2'),
oauth_name: 'google',
access_token: '<JWT>',
account_id: 'people/<ACCOUNT-ID>',
account_email: 'gtucker@gtucker.io',
expires_at: 1737020542,
refresh_token: null
}
]
}
with the sensitive bits removed i.e. HASHED_PASSWORD, JWT and ACCOUNT-ID.
Note
A refresh token may also be issued to stay logged in longer than the JWT expiry period. This feature isn't currently supported.