CREATE TABLE application_sessions ( session_id SERIAL NOT NULL PRIMARY KEY, user_id UUID NOT NULL REFERENCES users(user_id), application_id TEXT NOT NULL, started_at_utc TIMESTAMP NOT NULL, last_seen_at_utc TIMESTAMP NOT NULL ); CREATE INDEX ON application_sessions (user_id); COMMENT ON TABLE application_sessions IS 'Stores the sessions that involve an OIDC application and a user.'; COMMENT ON COLUMN application_sessions.user_id IS 'UUID of the user.'; COMMENT ON COLUMN application_sessions.application_id IS 'client_id of the OpenID Connect application for which this session is issued.'; COMMENT ON COLUMN application_sessions.started_at_utc IS 'Time when this session was started.'; COMMENT ON COLUMN application_sessions.last_seen_at_utc IS 'Time when we last heard of activity in this session. Does not mean the user has not been using the application since.'; CREATE TABLE application_access_tokens ( access_token_hash BYTEA NOT NULL PRIMARY KEY, session_id INTEGER NOT NULL REFERENCES application_sessions(session_id) ON DELETE CASCADE, issued_at_utc TIMESTAMP NOT NULL, expires_at_utc TIMESTAMP NOT NULL, created_from_refresh_token_hash BYTEA UNIQUE -- intentionally nullable ); CREATE INDEX ON application_access_tokens (session_id); COMMENT ON TABLE application_access_tokens IS 'Stores the hash of access tokens that have been issued to applications on the user''s behalf.'; COMMENT ON COLUMN application_access_tokens.access_token_hash IS 'BLAKE2s-256 hash of the refresh token.'; COMMENT ON COLUMN application_access_tokens.session_id IS 'ID of the session. This access token will cease to exist if the session is deleted.'; COMMENT ON COLUMN application_access_tokens.created_from_refresh_token_hash IS 'If set, this is the hash of the refresh token that was used to create this access token. This lets us track acknowledgement of a refresh.'; COMMENT ON COLUMN application_access_tokens.issued_at_utc IS 'Time when this access token was issued.'; COMMENT ON COLUMN application_access_tokens.expires_at_utc IS 'Time when this access token expires.'; CREATE TABLE application_refresh_tokens ( refresh_token_hash BYTEA NOT NULL PRIMARY KEY, session_id INTEGER NOT NULL REFERENCES application_sessions(session_id) ON DELETE CASCADE, created_from_refresh_token_hash BYTEA UNIQUE, -- intentionally nullable issued_at_utc TIMESTAMP NOT NULL, expires_at_utc TIMESTAMP NOT NULL ); CREATE INDEX ON application_refresh_tokens (session_id); COMMENT ON TABLE application_refresh_tokens IS 'Stores the hash of refresh tokens that have been issued to applications on the user''s behalf.'; COMMENT ON COLUMN application_refresh_tokens.refresh_token_hash IS 'BLAKE2s-256 hash of the refresh token.'; COMMENT ON COLUMN application_refresh_tokens.session_id IS 'ID of the session. This refresh token will cease to exist if the session is deleted.'; COMMENT ON COLUMN application_refresh_tokens.created_from_refresh_token_hash IS 'If set, this is the hash of the refresh token that was used to create this refresh token. This lets us track acknowledgement of a refresh.'; COMMENT ON COLUMN application_refresh_tokens.issued_at_utc IS 'Time when this refresh token was issued.'; COMMENT ON COLUMN application_refresh_tokens.expires_at_utc IS 'Time when this refresh token expires.';