Claude-assisted improvements (untested)
- dev auth flow (side-step OAuth) - db event processing integration tests - dev scripts (eg Makefile) - db / test db migration setup scripts.
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
package authentication
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
// DevLogin mints a local session for userID without going through the real
|
||||
// Auth0 OAuth flow. It writes a real oauth_users/oauth_tokens row, so every
|
||||
// other code path (identity lookup, account linking/creation, cookie
|
||||
// handling) treats it exactly like a normal login.
|
||||
//
|
||||
// Only ever call this from a route gated on an explicit dev-mode flag -
|
||||
// never wire it up unconditionally, since it lets the caller authenticate
|
||||
// as any user_id with no credentials.
|
||||
func (a *Authenticator) DevLogin(ctx context.Context, userID, name string) (accessToken string, expiration time.Time, err error) {
|
||||
tokenBytes := make([]byte, 32)
|
||||
if _, err := rand.Read(tokenBytes); err != nil {
|
||||
return "", time.Time{}, fmt.Errorf("failed to generate access token: %w", err)
|
||||
}
|
||||
accessToken = "dev_" + hex.EncodeToString(tokenBytes)
|
||||
|
||||
// Set far in the future so the near-expiry refresh path in
|
||||
// server/auth never tries to refresh a token that has no real
|
||||
// Auth0-side refresh token behind it.
|
||||
expiration = time.Now().Add(365 * 24 * time.Hour)
|
||||
|
||||
if _, err = a.db.Exec(
|
||||
ctx,
|
||||
`
|
||||
WITH ensured_user AS (
|
||||
INSERT INTO oauth_users (user_id)
|
||||
VALUES (@user_id)
|
||||
ON CONFLICT DO NOTHING
|
||||
)
|
||||
INSERT INTO oauth_tokens (
|
||||
access_token,
|
||||
token_type,
|
||||
refresh_token,
|
||||
expiry,
|
||||
|
||||
id_token_issuer,
|
||||
id_token_audience,
|
||||
id_token_subject,
|
||||
id_token_expiry,
|
||||
id_token_issued_at,
|
||||
id_token_nonce,
|
||||
id_token_access_token_hash,
|
||||
|
||||
id_token_custom_claims_family_name,
|
||||
id_token_custom_claims_given_name,
|
||||
id_token_custom_claims_name,
|
||||
id_token_custom_claims_nickname,
|
||||
id_token_custom_claims_picture,
|
||||
id_token_custom_claims_updated_at
|
||||
)
|
||||
VALUES (
|
||||
@access_token,
|
||||
'dev',
|
||||
'',
|
||||
@expiry,
|
||||
|
||||
'dev-auth-bypass',
|
||||
@audience,
|
||||
@user_id,
|
||||
@expiry,
|
||||
NOW(),
|
||||
'',
|
||||
'',
|
||||
|
||||
@name,
|
||||
@name,
|
||||
@name,
|
||||
@name,
|
||||
'',
|
||||
NOW()
|
||||
)
|
||||
`,
|
||||
pgx.NamedArgs{
|
||||
"access_token": accessToken,
|
||||
"expiry": expiration,
|
||||
"user_id": userID,
|
||||
"name": name,
|
||||
"audience": pgtype.FlatArray[string]{"dev"},
|
||||
},
|
||||
); err != nil {
|
||||
return "", time.Time{}, fmt.Errorf("failed to save dev session: %w", err)
|
||||
}
|
||||
|
||||
return accessToken, expiration, nil
|
||||
}
|
||||
Reference in New Issue
Block a user