Skip to content

Fix authorization server startup and OAuth grant flows - #1

Open
joneja09 wants to merge 1 commit into
mainfrom
cursor/review-auth-api-updates-b700
Open

Fix authorization server startup and OAuth grant flows#1
joneja09 wants to merge 1 commit into
mainfrom
cursor/review-auth-api-updates-b700

Conversation

@joneja09

Copy link
Copy Markdown
Owner

Review

This API is a solid start at a custom OAuth 2.0 authorization server (authorization code + PKCE, refresh token, client credentials) on ASP.NET Core Identity. It was not production-ready: several issues would have prevented the app from booting or completing a token exchange.

Yes, updates were needed. This PR applies the high-severity functional and security fixes. Larger product work (consent UI, hashed client secrets, migrations, admin client registration) is called out below rather than being rewritten here.

What was broken

  • Startup/DI: JWT config used Jwt:Secret while tokens were signed with Jwt:SecretKey. IClientService / IEncryptionService were not registered. Identity used IdentityRole while the DbContext used ApplicationRole. Placeholder encryption keys were not valid AES keys.
  • Authorization codes could not be redeemed: codes were AES-encrypted with a random IV (so they cannot be looked up) and then searched by plaintext.
  • Refresh tokens were unusable: login never stored them; the code grant passed arguments in the wrong order; storing both user and client IDs threw.
  • OAuth clients would not bind: token requests expected GrantType instead of grant_type.
  • Interactive /authorize used JWT challenge, so cookie login could not complete the code flow. GET /account/login returned a missing Razor view.
  • Secrets were committed in appsettings.json. HTTPS metadata was disabled. Dockerfile restore omitted ServiceDefaults.

What this PR changes

  • Hash authorization codes and refresh tokens (SHA-256) instead of encrypting them for lookup.
  • Bind standard OAuth form fields, rotate refresh tokens, and return access_token / expires_in JSON.
  • Use Identity cookies for /authorize, add a login page, and keep JSON login at POST /account/login/token.
  • Register services, align JWT config, enable Aspire defaults, OpenAPI + Scalar, and health endpoints.
  • Require S256 PKCE when the client requires it; compare client secrets in constant time.
  • Add unit tests for PKCE, hashing, and encryption.

Verification

  • dotnet build and dotnet test: 9 tests passed.
  • Live HTTP checks (no SQL Server in this environment):
    • GET /account/login → 200 HTML
    • GET /openapi/v1.json documents /token and /account/* API routes
    • POST /token with an unknown grant → unsupported_grant_type
    • /health and /alive → 200
  • Full authorize → token exchange against SQL Server was not run here.

Still worth doing later

  • Hash client secrets at rest; add client registration/admin APIs.
  • EF Core migrations and a real database in local/dev setup.
  • Consent screen, refresh-token reuse detection, public clients (no secret).
  • Consider OpenIddict or Duende if you need a full OpenID Connect provider rather than a custom OAuth subset.
Open in Web Open in Cursor 

The authorization server could not boot or complete grant exchanges: JWT config keys did not match, required services were not registered, authorization codes were encrypted with a random IV then looked up by plaintext, and refresh tokens were never stored. Hash codes and refresh tokens, bind standard OAuth form fields, use Identity cookies for /authorize, and add a login page plus unit tests.

Co-authored-by: Jeff Jones <joneja09@users.noreply.github.com>
@joneja09
joneja09 marked this pull request as ready for review August 26, 2026 14:03
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.

2 participants