Skip to content

Comments

feat: Steam profile display and admin auth improvements#234

Merged
fank merged 10 commits intomainfrom
feat/steam-auth
Feb 24, 2026
Merged

feat: Steam profile display and admin auth improvements#234
fank merged 10 commits intomainfrom
feat/steam-auth

Conversation

@fank
Copy link
Member

@fank fank commented Feb 24, 2026

Summary

  • Add optional admin.steamApiKey config to fetch Steam player display names and avatars via the Steam Web API (GetPlayerSummaries/v2)
  • Store profile data (name, avatar URL) in JWT custom claims so /auth/me returns them without extra API calls
  • Admin badge now shows the Steam avatar and display name instead of a hardcoded "A" and raw Steam64 ID (graceful fallback when no API key is configured)
  • Fix comma-separated env var parsing for OCAP_ADMIN_ALLOWEDSTEAMIDS — viper doesn't split strings into slices automatically
  • Document admin authentication settings in README (config table, env vars, example)

Test plan

  • go test ./internal/server/... — all pass (27 new test cases)
  • npx vitest run — all 777 frontend tests pass
  • go build ./cmd/ocap-webserver — builds clean
  • Manual: configure steamApiKey, login via Steam, verify avatar + name in admin badge
  • Manual: without steamApiKey, verify fallback to Steam ID
  • Manual: set OCAP_ADMIN_ALLOWEDSTEAMIDS=id1,id2 env var, verify both IDs are authorized

fank added 4 commits February 24, 2026 15:23
Machine uploads keep using the shared `secret` form field. Human admin
login now goes through Steam OpenID 2.0: the browser redirects to Steam,
returns to /api/v1/auth/steam/callback, and the backend verifies the
response, checks the Steam ID against an allowlist, and issues a JWT
with the Steam ID as subject.

- Add github.com/yohcop/openid-go dependency
- Add AllowedSteamIDs config (setting.json + OCAP_ADMIN_ALLOWEDSTEAMIDS env)
- JWT Create() now accepts a subject parameter for Steam ID embedding
- Replace POST /auth/login with GET /auth/steam + GET /auth/steam/callback
- Auth errors redirect to frontend with ?auth_error= for user-friendly display
- Frontend: remove LoginModal, add "Sign in with Steam" button + cookie handoff
- Update all backend and frontend tests
The Vite dev server proxies /api requests to the Go backend, but the
backend was using c.Request().Host (the proxy target) to build Steam
callback URLs and the final redirect. This caused Steam to redirect
back to localhost:5000 instead of localhost:5173, landing on a 404.

- Vite proxy now sends X-Forwarded-Host header for /api routes
- Backend reads X-Forwarded-Host when building callback URL, OpenID
  verification URL, and auth redirect target
Replace the inline red text next to the sign-in button with a centered
toast that slides in from the top, auto-dismisses after 5 seconds, and
has a manual close button.
- Add optional Steam Web API key to fetch player display names and avatars
- Store Steam profile data (name, avatar) in JWT custom claims
- Show Steam avatar and display name in admin badge (falls back to Steam ID)
- Fix comma-separated env var parsing for AllowedSteamIDs
- Update README with admin authentication documentation
- Add comprehensive test coverage for JWT claims, Steam API, and splitCSV
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @fank, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly overhauls the admin authentication mechanism by integrating Steam OpenID, moving away from a simple shared secret. The change not only enhances security by leveraging Steam's robust authentication but also enriches the admin user experience by displaying personalized Steam profile information. Additionally, it addresses a critical configuration parsing bug and updates documentation to ensure clarity for deployment and setup.

Highlights

  • Steam OpenID Integration for Admin Authentication: Implemented Steam OpenID for admin login, replacing the previous secret-based authentication. Admins now authenticate via their Steam account against an allowlist of Steam64 IDs.
  • Enhanced Admin Profile Display: Added an optional admin.steamApiKey configuration to fetch and display Steam player names and avatars in the admin badge, providing a more personalized experience. A graceful fallback to the raw Steam64 ID is in place if no API key is configured.
  • JWT Custom Claims for Steam Profile Data: Steam profile data (display name and avatar URL) is now stored directly within JWT custom claims, eliminating the need for additional API calls to retrieve this information after initial authentication.
  • Improved Environment Variable Parsing: Fixed an issue where comma-separated environment variables for OCAP_ADMIN_ALLOWEDSTEAMIDS were not correctly parsed into a slice, ensuring proper configuration of admin allowlists.
  • Updated Documentation and Configuration Examples: The README.md and setting.json.example files have been updated to reflect the new admin authentication settings, including admin.sessionTTL, admin.allowedSteamIds, and admin.steamApiKey.
  • Frontend UI/UX Enhancements: The frontend has been updated to support the new Steam login flow, display Steam avatars and names in the admin badge, and provide toast notifications for authentication errors. The old secret-based login modal has been removed.
Changelog
  • README.md
    • Documented new admin authentication settings, including Steam API key and allowed Steam IDs.
    • Updated example setting.json and environment variables for admin configuration.
  • egg-ocap2-web.json
    • Added configuration options for OCAP_ADMIN_ALLOWEDSTEAMIDS and OCAP_ADMIN_STEAMAPIKEY.
  • go.mod
    • Added github.com/yohcop/openid-go dependency.
  • go.sum
    • Updated checksums for new openid-go dependency and other Go modules.
  • internal/server/handler.go
    • Imported openid-go for Steam OpenID functionality.
    • Added openIDVerifier, openIDCache, openIDNonceStore, and steamAPIBaseURL fields to the Handler struct.
    • Initialized OpenID components in NewHandler.
    • Replaced POST /api/v1/auth/login with GET /api/v1/auth/steam and GET /api/v1/auth/steam/callback routes.
  • internal/server/handler_admin_test.go
    • Updated hdlr.jwt.Create() calls to pass an empty string for the subject.
    • Removed the e.POST("/api/v1/auth/login", hdlr.Login) route.
    • Modified the admin flow test to directly create a JWT instead of simulating a secret-based login.
  • internal/server/handler_auth.go
    • Replaced the secret-based Login handler with SteamLogin and SteamCallback for OpenID authentication.
    • Added helper functions extractSteamID, isSteamIDAllowed, requestHost, requestScheme, fetchSteamProfileFrom, and randomHex.
    • Updated GetMe to include Steam profile data (ID, name, avatar) in the response.
  • internal/server/handler_auth_test.go
    • Replaced newAuthHandler with newSteamAuthHandler for Steam-specific testing setup.
    • Added extensive tests for Steam OpenID login flow, nonce handling, Steam ID extraction, allowlist checks, and fetching Steam profile data.
    • Removed tests for the old secret-based login.
    • Updated GetMe tests to verify Steam ID and profile data in the response.
  • internal/server/handler_test.go
    • Updated jwtMgr.Create() call to pass an empty string for the subject.
  • internal/server/jwt.go
    • Introduced SteamClaims struct to extend standard JWT claims with SteamName and SteamAvatar.
    • Modified Create method to accept a subject and ClaimOptions for custom claims.
    • Added ClaimOption type and WithSteamProfile function to set Steam profile data.
    • Added Subject method to retrieve the JWT subject.
    • Added Claims method to retrieve all custom Steam claims from a token.
  • internal/server/jwt_test.go
    • Updated mgr.Create() calls to pass an empty string or a specific subject.
    • Added tests for Subject, Claims, WithSteamProfile, and various invalid token scenarios for claims.
  • internal/server/setting.go
    • Added AllowedSteamIDs (slice of strings) and SteamAPIKey (string) to the Admin struct.
    • Updated viper defaults and envKeys list to include new admin settings.
    • Implemented splitCSV function to correctly parse comma-separated environment variables for AllowedSteamIDs.
  • internal/server/setting_test.go
    • Added tests for Admin.AllowedSteamIDs configuration.
    • Added tests for Admin.SteamAPIKey configuration.
    • Added tests for the new splitCSV utility function.
  • setting.json.example
    • Added allowedSteamIds and steamApiKey to the admin section.
  • ui/src/data/tests/api-client.test.ts
    • Removed tests for the old login method.
    • Added tests for getSteamLoginUrl and consumeAuthCookie.
  • ui/src/data/api-client.ts
    • Updated AuthState interface to include steamId, steamName, and steamAvatar.
    • Removed the login method.
    • Added getSteamLoginUrl and consumeAuthCookie methods for Steam authentication.
  • ui/src/hooks/tests/useAuth.test.tsx
    • Updated mock ApiClient to reflect changes (removed mockLogin, added mockGetSteamLoginUrl, mockConsumeAuthCookie).
    • Modified tests to check consumeAuthCookie on mount and loginWithSteam for redirection.
  • ui/src/hooks/useAuth.tsx
    • Updated Auth interface to include steamId, steamName, steamAvatar, authError, dismissAuthError, and loginWithSteam.
    • Removed the login method.
    • Added logic to handle auth_error query parameter from Steam callback and display a toast.
    • Implemented consumeAuthCookie on mount to process authentication tokens from cookies.
    • Updated logout to clear Steam profile states.
  • ui/src/pages/mission-selector/MissionSelector.module.css
    • Added CSS classes for adminAvatarImg to style Steam avatars.
    • Added CSS classes for toast and toastClose components, including toastIn keyframes for animation.
  • ui/src/pages/mission-selector/MissionSelector.tsx
    • Removed LoginModal component and related state (showLoginModal, loginError).
    • Integrated new useAuth hooks for steamId, steamName, steamAvatar, authError, dismissAuthError, and loginWithSteam.
    • Updated the 'Sign in' button to trigger loginWithSteam.
    • Modified the admin badge to display Steam avatar and name using Show components.
    • Added a Toast component for displaying authentication errors.
  • ui/src/pages/mission-selector/tests/MissionSelector.test.tsx
    • Removed tests related to the old secret-based login modal.
    • Updated tests to reflect the new 'Sign in with Steam' button and the removal of the login modal.
  • ui/vite.config.ts
    • Modified the /api proxy configuration to include X-Forwarded-Host header for correct Steam callback URLs during development.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

github-actions bot commented Feb 24, 2026

Coverage Report for ui

Status Category Percentage Covered / Total
🔵 Lines 78.48%
⬆️ +0.01%
2878 / 3667
🔵 Statements 75.16%
⬆️ +0.03%
3749 / 4988
🔵 Functions 75%
⬆️ +0.02%
1011 / 1348
🔵 Branches 65.39%
⬆️ +0.23%
1304 / 1994
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
ui/src/data/api-client.ts 81.63%
⬇️ -0.18%
87.17%
⬆️ +1.81%
95.83%
⬆️ +0.18%
80.64%
⬇️ -0.41%
152-154, 178-182, 229-265
ui/src/hooks/useAuth.tsx 100%
⬆️ +3.34%
81.81%
⬇️ -1.52%
100%
🟰 ±0%
100%
⬆️ +3.34%
ui/src/pages/mission-selector/MissionSelector.tsx 85.25%
⬇️ -0.41%
76.42%
⬆️ +1.25%
81.95%
⬇️ -0.22%
91.31%
⬇️ -0.47%
83-94, 122, 123, 149-150, 252-254, 275-276, 278-279, 287, 294-297, 321, 437, 438-439, 441-442, 480, 568-569, 580
Generated in workflow #133 for commit 655beab by the Vitest Coverage Report Action

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request significantly enhances the authentication mechanism by migrating from a simple secret-based login to a more robust Steam OpenID integration for admin access. The changes span both the backend (Go) and frontend (SolidJS/TypeScript), introducing new API endpoints, JWT claims for Steam profile data, and UI elements to display user avatars and names. The documentation and configuration examples have been updated to reflect these new settings. Overall, the implementation appears solid, with good attention to detail in handling OpenID flows, cookie management, and error reporting. All review comments provided are valid and contribute to the quality of the pull request.

fank added 6 commits February 24, 2026 16:07
Cover handler_auth.go gaps (requestHost, requestScheme, authRedirect
with prefix, SteamCallback error/invalid paths), useAuth.tsx gaps
(auth_error URL handling, dismissAuthError, steamName/steamAvatar
population and clearing on logout), and MissionSelector Toast component.
Rename nonceCookie/tokenCookie → cookieNonce/cookieToken for cleaner
grouping. Add comment explaining the 30s token cookie design. Note
comma-separated env var format for allowedSteamIds in README.
The cookie was just shuttling the JWT from the Steam callback redirect
to the frontend. Simpler to pass it as ?auth_token= in the redirect
URL — same pattern already used for ?auth_error=. The frontend reads
both params on mount and cleans the URL.
@github-actions
Copy link

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/OCAP2/web/internal/server 87.08% (+0.92%) 👍

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/OCAP2/web/internal/server/handler.go 83.94% (+0.34%) 193 (+4) 162 (+4) 31 👍
github.com/OCAP2/web/internal/server/handler_auth.go 92.08% (-3.57%) 101 (+78) 93 (+71) 8 (+7) 👎
github.com/OCAP2/web/internal/server/jwt.go 93.10% (+4.21%) 29 (+20) 27 (+19) 2 (+1) 👍
github.com/OCAP2/web/internal/server/setting.go 94.44% (+1.11%) 54 (+9) 51 (+9) 3 👍

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/OCAP2/web/internal/server/handler_admin_test.go
  • github.com/OCAP2/web/internal/server/handler_auth_test.go
  • github.com/OCAP2/web/internal/server/handler_test.go
  • github.com/OCAP2/web/internal/server/jwt_test.go
  • github.com/OCAP2/web/internal/server/setting_test.go

@fank fank merged commit 264fbf8 into main Feb 24, 2026
3 checks passed
@fank fank deleted the feat/steam-auth branch February 24, 2026 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant