-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Goal
Enable end-users to sign in to EVKX.net using Gmail (Google), Facebook, GitHub, LinkedIn, and Microsoft, create a single EVKX profile with a unique username, and optionally link multiple provider accounts to the same profile. Persist basic profile settings (language, units, country scope) and user authorization scopes in Azure PostgreSQL using Entity Framework Core, under a dedicated profile schema.
Why
- Reduce friction for sign-in and cover a broad set of users with common providers.
- Ensure EVKX has a stable internal user identity independent of any external provider.
- Improve personalization (language/units/country-filter defaults).
- Enable controlled access to features and admin tooling using a scope-based authorization model.
Scope
Authentication & Providers
- Support sign-in with: Google (Gmail), Facebook, GitHub, LinkedIn, Microsoft.
- Provider must provide email (required for account creation / linking).
- Store provider identity for stable linking (provider/issuer + subject/provider user id).
Profile creation & username
- First-time login requires the user to select/create a unique username.
- Enforce uniqueness (case-insensitive recommended).
- Reserve/deny problematic usernames (admin, support, evkx, etc.) and optionally apply a profanity list.
Account linking (one profile, many providers)
-
A profile can have multiple linked login methods (e.g. Google + Microsoft + GitHub).
-
A user can log in via any linked provider and end up in the same profile.
-
Safe linking flow:
- User must already be authenticated to link another provider (recommended), or
- Verified email match with explicit confirmation (higher risk; avoid if possible).
Profile settings
Store and expose:
- Preferred language (e.g.
en,nb,de, etc.) - Preferred units: Metric / Imperial
- Default EV search country filter (optional; e.g.
NO,DE,US)
Scopes & authorization
- EVKX uses a scope-based authorization model to control access to features and admin capabilities.
- Users receive default scopes automatically (configured in a scope catalog).
- Site admins can grant additional scopes and revoke them later.
- Store a durable audit trail for scope changes (who, when, why).
- Expose effective scopes in API so UI can enable/disable features cleanly.
Examples of scope names (illustrative):
profile.read,profile.writeev.search.advancedev.compareev.spec.editcontent.editadmin.site
Acceptance criteria
Authentication / Profile
- User can sign in with Google, Facebook, GitHub, LinkedIn, Microsoft.
- On first login, user is prompted to create a unique username before continuing.
- Email is collected from provider and stored; login fails gracefully if email is missing/unverified (policy decided below).
- User can link an additional provider account from profile settings and then log in using any linked provider to the same profile.
- Profile settings are persisted and returned via API; UI reflects current settings.
- Language/units/country defaults apply to relevant UI pages (at minimum: EV search defaults).
- Basic audit logging exists for: login, linking/unlinking, username creation/change.
Scopes
- A scope catalog exists with support for default scopes.
- On profile creation, user receives all scopes marked as default.
- Admin can grant an additional scope to a user.
- Admin can revoke a previously granted scope.
- System exposes the user’s effective scopes via API (
/me/scopesor included in/me). - Admin scope changes are auditable (grantedBy, grantedAt, revokedAt, reason).
- At least one real feature is protected by scopes end-to-end (API + UI gating), e.g. “EV Spec Admin access”.
UX notes
First-time login flow
- “Sign in with …”
- If no profile exists → “Create username”
- Profile created → continue to site
Profile page includes
- Connected accounts list (Google, Facebook, GitHub, LinkedIn, Microsoft)
- “Link new provider”
- Settings: Language, Units, Default country filter
Admin UI (for scopes)
-
User lookup/search
-
User details: profile + linked providers + scopes
-
Scope management:
- List effective scopes
- Grant scope (dropdown from catalog)
- Revoke scope (requires reason if desired)
Data model (suggested)
Storage: Azure PostgreSQL, schema profile, accessed via EF Core.
UserProfile (profile.user_profile)
id(GUID)username(unique, normalized)email(primary)preferredLanguagepreferredUnits(Metric/Imperial)defaultCountry(nullable)createdAt,updatedAt
UserLogin (profile.user_login)
id(GUID)userProfileId(FK)provider(string/enum: google, facebook, github, linkedin, microsoft)providerSubject(string)issuer(string, recommended)email(as seen from provider, optional)createdAt
Indexes
- Unique: (
provider,providerSubject) (or (issuer,providerSubject) depending on your design) - Unique: normalized
username
Scopes data model
Scope catalog (profile.scope)
id(GUID)name(unique, normalized)description(string)isDefault(bool)createdAt,updatedAt
Indexes
- Unique: (
name)
User scope grants (profile.user_scope_grant)
id(GUID)userProfileId(FK →profile.user_profile.id)scopeId(FK →profile.scope.id)grantType(string/enum):default,admin(optionallysystem)grantedByUserProfileId(nullable FK →profile.user_profile.id)grantedAt(timestamp)revokedAt(nullable timestamp)reason(nullable string)
Indexes / constraints
-
Unique active grant (Postgres partial unique index):
- (
userProfileId,scopeId) WHERErevokedAt IS NULL
- (
-
Index: (
userProfileId,revokedAt) -
Index: (
scopeId,revokedAt)
Default scope behavior
- On new profile creation: insert grants for all
scope.isDefault = true. - Optional: “sync defaults” job/endpoint to backfill new default scopes to existing users.
API (suggested)
Auth / profile
POST /auth/login/{provider}(challenge/start)POST /auth/login/{provider}/callback(callback handling)GET /mePUT /me/settingsPOST /me/link/{provider}(start linking)POST /me/link/{provider}/callbackDELETE /me/link/{provider}(optional, with safeguards)
Scopes
GET /me/scopes(or include inGET /me)
Admin (scopes)
GET /admin/scopes(list scope catalog)POST /admin/scopes(create/update scope catalog entries; optional)GET /admin/users(search users; optional)GET /admin/users/{userId}/scopesPOST /admin/users/{userId}/scopes/{scopeName}(grant; reason optional/required)DELETE /admin/users/{userId}/scopes/{scopeName}(revoke; reason optional/required)
Tasks
Backend
-
Implement ASP.NET Core auth with external providers:
- Google (Gmail)
- GitHub
- Microsoft
-
Implement provider login + callback handling
-
Implement profile bootstrap flow (pending username)
-
Implement username validation + reservation + normalization
-
Implement linking flow + storage of provider identities (issuer + subject)
-
Implement profile settings persistence + endpoints
-
Create PostgreSQL schema
profile+ EF Core migrations -
Add audit logging events (login, linking, username actions)
Backend (scopes)
- Implement
Scopecatalog model + migrations - Implement
UserScopeGrantmodel + migrations (including partial unique index) - Seed initial scope catalog (including default scopes)
- On profile creation: grant default scopes
- Implement effective-scope resolution (active grants only)
- Add authorization checks based on scopes (policy/handler approach recommended)
- Implement admin endpoints for scope grant/revoke + audit trail
Frontend
- Login UI (provider buttons)
- First-time “Create username” screen
- Profile settings page
- Connected accounts UI + link/unlink actions
- Apply defaults in EV search (language/units/country)
- UI gating for at least one scoped feature (hide/disable actions based on scopes)
Admin UI (scopes)
-
Admin user search + user details view
-
Scope management UI:
- List effective scopes
- Grant scope (select from catalog)
- Revoke scope (optional reason)
-
Display audit info for scope changes (who/when)
Security / Compliance
- Decide email policy: must be verified? what if provider doesn’t return email?
- Protect linking against account takeover (require authenticated session for linking)
- Rate-limit username checks + login attempts
- Ensure scope admin endpoints require an admin scope (e.g.
admin.site)
Tests
-
Unit tests for username rules and normalization
-
Unit tests for linking rules and takeover protection
-
Unit tests for scope resolution (default, admin grants, revocation)
-
Integration tests for external login callbacks (mocked)
-
Integration tests for EF Core migrations (schema + constraints)
-
E2E flows:
- New user creates profile + receives default scopes
- Returning user login
- Link second provider
- Admin grants scope → feature becomes available
Open questions (add as checklist)
- Email policy: must be verified? what if provider doesn’t return email?
- Include
issuerin identity uniqueness key for provider identities? (recommended for OIDC) - Allow changing username later? if yes, frequency limits?
- Should default scopes be granted only at creation, or also synced when new defaults are added?
- What is the initial minimal scope set for all users vs power-users/admins?