First login¶
With all three containers running and at least one directory sync completed, you can log in.
1. Confirm the user you will log in as is in Workspace¶
Whoever you log in as must be:
- an active user in your Workspace domain (
Suspended=false,Archived=false), - with a verified primary email,
- and present in the directory snapshot ARIS just pulled.
If you skipped creating an aris-admin@<domain> group earlier, that's fine — you will log in as a read-scope user. To get the admin scopes, add yourself to the aris-admin@<domain> group and either restart core or wait for the next sync.
2. Open the web UI¶
Browse to http://localhost:3001 (or whatever you set NEXTAUTH_URL to).
The middleware will redirect you to /login because there is no session yet. Click Sign in with Google.
3. Complete the Google login¶
Pick the account you want to sign in as. Google handles the OAuth dance and redirects back to /api/auth/callback/google. NextAuth then runs the signIn gate:
- Looks up your Google
subinauthentication_identity. - If found, reads the matching
person.status. Active → continue. Anything else → reject. - If verified and active, mints a NextAuth session cookie and redirects you to
/.
You should land on the home page. Open the browser's network tab and visit any authenticated route to confirm cookies are set.
4. Confirm scopes¶
The home page (or any route that calls /v1/whoami) shows the scopes ARIS derived for you. You should see:
[read]— default user, no special groups.[read, audit]— you're inaris-auditor@<your-domain>.[read, audit, admin]— you're inaris-admin@<your-domain>.
If you expected admin and got read, see Troubleshooting → "I'm in the admin group but only got read".
5. (Optional) Hit /v1/whoami directly¶
To confirm core is wired up end to end without going through the UI, you can mint a bridge token by hand and curl core directly. This requires sharing the same ARIS_AUTH_TOKEN_SECRET that core was given.
Save this script outside the repo as mint-token.go and run it with the secret in your env:
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"time"
)
func main() {
secret := os.Getenv("ARIS_AUTH_TOKEN_SECRET")
sub := os.Getenv("ARIS_TEST_USER_ID") // a person.user_id from your DB
header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"HS256","typ":"JWT"}`))
payload := map[string]any{
"sub": sub,
"aud": "core",
"iat": time.Now().Unix(),
"exp": time.Now().Add(5 * time.Minute).Unix(),
}
pb, _ := json.Marshal(payload)
body := header + "." + base64.RawURLEncoding.EncodeToString(pb)
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(body))
sig := base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
fmt.Println(body + "." + sig)
}
Then:
# Find a user_id from your dev DB:
docker compose exec db psql -U aris -d aris -c "SELECT user_id, primary_email FROM person LIMIT 1;"
# Mint a token (requires Go on the host):
ARIS_AUTH_TOKEN_SECRET=<from .env> \
ARIS_TEST_USER_ID=<the user_id above> \
TOKEN=$(go run mint-token.go)
# Call core:
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8080/v1/whoami | jq
# {"user_id":"...", "email":"...", "scopes":["read", ...]}
The token is valid for 5 minutes; if you need to keep poking, re-mint.
You're installed. Next steps:
- Operate / Production hardening — when you move beyond a single-host evaluation.
- Troubleshooting — for any of the common surprises.