-
Notifications
You must be signed in to change notification settings - Fork 605
fix: add issuer validation #2322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## What kind of change does this PR introduce? This PR updates `performRateLimiting` to treat the rate limit header value as a comma-separated list and enforce rate limiting based on the first value in that list. ## What is the current behavior? Certain HTTP headers, such as `X-Forwarded-For` and other headers that are combined according to RFC 7230, can be represented as a comma-separated list of values. Intermediate proxies may add their own values to these headers, modifying the resulting value. For example, an end user with a single IP address proxied through a fleet of load balancers using the X-Forwarded-For header may be associated with multiple `X-Forwarded-For` header values, e.g., `2.2.2.2,100.100.100.100` and `2.2.2.2,300.300.300.300`. The current implementation of `performRateLimiting` treats each of these as separate rate limiting keys. ## What is the new behavior? This PR splits the rate limit header by commas and takes the first value (with whitespace removed) to use as the rate limiting key. Note that this logic is superficially similar to the `utilities.GetIPAddress` function with two key differences. In `performRateLimiting`, there is no set format for a given rate limiting key, nor is there a fallback value after the first value in the list that the API should use.
Increase tests coverage and verify phone change functionality in response to supabase/supabase#40797 - Add defensive change to anonymous rate limits test - This function relies on low anon rate limit (loops over rate limit) - Rename getAccessToken to getEmailAccessToken and add generic getAccessToken helper - Rename signupAndConfirm to signupAndConfirmEmail - Expand phone signup and phone change e2e tests: - Capture and verify OTP from SendSMS hook - Validate one-time token creation and user state transitions - Add full phone change flow, including OTP verification - Update MFA-related tests to use new helper names Co-authored-by: Chris Stockton <[email protected]>
## What kind of change does this PR introduce? Big fix for #1729, #1848, #1983, and #2040 with an additional type fix. ## What is the current behavior? The auth service cannot be deployed in a net new environment on PostgreSQL 17. ## What is the new behavior? The service is running properly with PostgreSQL 17 in a cleanroom environment. ## Additional context Here is a redacted version of the terraform I used to deploy it with. I used my own container build with these fixes, `ghcr.io/siennathesane/auth:v2.175.0`, that you can use to verify the fix is valid, if you want. ```hcl locals { f2-auth-db-namespace = "auth" } resource "kubernetes_service_account" "f2-auth" { metadata { name = "f2-auth" namespace = var.namespace } } resource "kubernetes_manifest" "f2-auth-db" { manifest = { "apiVersion" = "postgresql.cnpg.io/v1" "kind" = "Database" "metadata" = { "name" = "f2-auth-db" "namespace" = var.namespace } "spec" = { "cluster" = { "name" = kubernetes_manifest.f2-cluster.object.metadata.name } "allowConnections" = true "name" = local.f2-auth-db-namespace "owner" = kubernetes_secret_v1.f2-auth-db.data.username "schemas" = [{ "name" = local.f2-auth-db-namespace "owner" = kubernetes_secret_v1.f2-auth-db.data.username }] } } } resource "kubernetes_config_map_v1" "f2-auth-initdb" { metadata { name = "sql-commands" namespace = var.namespace } data = { "script.sql" = <<-EOT ALTER USER ${kubernetes_secret_v1.f2-auth-db.data.username} WITH LOGIN CREATEROLE CREATEDB REPLICATION BYPASSRLS; GRANT ${kubernetes_secret_v1.f2-auth-db.data.username} TO postgres; CREATE SCHEMA IF NOT EXISTS ${local.f2-auth-db-namespace} AUTHORIZATION ${kubernetes_secret_v1.f2-auth-db.data.username}; GRANT CREATE ON DATABASE postgres TO ${kubernetes_secret_v1.f2-auth-db.data.username}; ALTER USER ${kubernetes_secret_v1.f2-auth-db.data.username} SET search_path = '${local.f2-auth-db-namespace}'; EOT } } resource "kubernetes_secret_v1" "f2-auth-db" { metadata { name = "auth-db" namespace = var.namespace labels = { "cnpg.io/reload" = "true" } } data = { username = "[REDACTED]" password = random_password.f2-auth-db-password.result database = "auth" } type = "kubernetes.io/basic-auth" } resource "kubernetes_secret_v1" "f2-auth-jwt" { metadata { name = "auth-jwt" namespace = var.namespace } data = { anonKey = "[REDACTED]" secret = "[REDACTED]" serviceKey = "[REDACTED]" } type = "Opaque" } resource "random_password" "f2-auth-db-password" { length = 16 special = false } resource "kubernetes_deployment_v1" "f2-auth" { depends_on = [kubernetes_manifest.f2-auth-db] timeouts { create = "2m" } metadata { name = "f2auth" labels = { "f2.pub/app" = "auth-${var.environment}" } namespace = var.namespace } spec { replicas = 1 selector { match_labels = { "f2.pub/app" = "auth-${var.environment}" } } template { metadata { labels = { "f2.pub/app" = "auth-${var.environment}" } } spec { image_pull_secrets { name = var.ghcr-pull-secret-name } init_container { name = "init-db" image = "postgres:17-alpine" command = ["psql", "-f", "/sql/script.sql"] env { name = "PGHOST" value = "${kubernetes_manifest.f2-cluster.object.metadata.name}-rw" } env { name = "PGPORT" value = "5432" } env { name = "PGDATABASE" value = kubernetes_secret_v1.f2-auth-db.data.database } env { name = "PGUSER" value = kubernetes_secret_v1.f2-auth-db.data.username } env { name = "PGPASSWORD" value = kubernetes_secret_v1.f2-auth-db.data.password } volume_mount { name = "sql-volume" mount_path = "/sql" } } volume { name = "sql-volume" config_map { name = kubernetes_config_map_v1.f2-auth-initdb.metadata[0].name } } container { image = "ghcr.io/siennathesane/auth:${var.goauth-version}" image_pull_policy = "Always" name = "auth" resources { limits = { cpu = "0.5" memory = "512Mi" } requests = { cpu = "250m" memory = "50Mi" } } port { name = "http" container_port = 9999 protocol = "TCP" } env { name = "GOTRUE_DB_DRIVER" value = "postgres" } env { name = "DB_NAMESPACE" value = "auth" } env { name = "DATABASE_URL" value = "postgres://${kubernetes_secret_v1.f2-auth-db.data.username}:[REDACTED]@${ kubernetes_manifest.f2-cluster.object.metadata.name}-rw:5432/${kubernetes_secret_v1.f2-auth-db.data.database}" } env { name = "GOTRUE_JWT_SECRET" value_from { secret_key_ref { name = "auth-jwt" key = "secret" } } } env { name = "API_EXTERNAL_URL" value = "http://[REDACTED]" } env { name = "GOTRUE_SITE_URL" value = "http://[REDACTED]" } env { name = "GOTRUE_API_HOST" value = "0.0.0.0" } env { name = "PORT" value = "9999" } } } } } } ``` Closes #1729 Closes #1848 Closes #1983 Closes #2040 Signed-off-by: Sienna Satterwhite <[email protected]> Co-authored-by: Chris Stockton <[email protected]>
## What kind of change does this PR introduce? Bug fix ## What is the current behavior? In fact, err is incorrect and should be terr. ## What is the new behavior? Feel free to include screenshots if it includes visual changes. ## Additional context Add any other context or screenshots. Signed-off-by: cangqiaoyuzhuo <[email protected]> Co-authored-by: Chris Stockton <[email protected]>
Because type creation resides in the do block it is all or nothing. When it's not a duplicate object that behavior is appropriate, but if it's because one of the types already exists then you will fail the creation of the other types. For example: * `aal_level` type already exists * `factor_status` & `factor_type` are missing Currently this would prevent `factor_status` & `factor_type` from ever getting created. Co-authored-by: Chris Stockton <[email protected]>
## Summary This PR loosens the validation for the `amr` (Authentication Method Reference) claim in custom access token hooks to accept both array of strings and array of objects, instead of only array of objects. - **Test Coverage**: Added two new test cases: - Modify amr to be array of strings - Verifies that `amr` as an array of strings passes validation - Modify amr to be array of objects - Verifies that `amr` as an array of objects still works (backward compatibility) ## Motivation This change provides more flexibility for custom access token hooks. [RFC-8176 ](https://www.rfc-editor.org/rfc/rfc8176.html#section-1)requires `amr` to be array of strings. ## Testing All tests pass, including: - Existing custom access token tests - New test for `amr` as array of strings - New test for `amr` as array of objects ## Backward Compatibility **Fully backward compatible** - The change only adds support for an additional format. Existing hooks that return `amr` as an array of objects will continue to work without any changes.
Removes dependency on the `pg_trgm` extension in the indexworker. This simplifies the rollout process related to extension creation and permissions at the cost of more restricted query patterns (i.e.: no contains queries on name and email `%term%`).
## What kind of change does this PR introduce? This PR adds support for IP address forwarding using a new header, `Sb-Forwarded-For`, optionally gated by `GOTRUE_SECURITY_SB_FORWARDED_FOR_ENABLED`. When this feature is enabled, both `utilities.GetIPAddress` and rate limiting will use the first value of the `Sb-Forwarded-For` header as the IP address/rate limiting key. If the feature is disabled or the `Sb-Forwarded-For` header contains an invalid value, Auth will fall back to existing behavior. ## What is the current behavior? There are currently two paths along which users are likely to use IP address information. The first is IP tracking (e.g., logging, MFA challenge validation, and CAPTCHA challenge validation). The second is rate limiting. Both of these follow slightly different logical paths, relying on the `X-Forwarded-For` header explicitly in the former case and a separate rate limiting key header in the latter. The presence of these two paths results in some friction for users. `X-Forwarded-For` can be (and frequently is) rewritten by proxies or otherwise spoofed, and there is no guarantee that a rate limiting key in the rate limit header is an IP address. ## What is the new behavior? The API uses a new middleware, `sbff.Middleware`, that parses the `Sb-Forwarded-For` header and inserts it into the request context if `GOTRUE_SECURITY_SB_FORWARDED_FOR_ENABLED` is true. Consumers of the `Sb-Forwarded-For` header can use `sbff.GetIPAddress` to retrieve the parsed IP address. `utilities.GetIPAddress` will prefer the result of `sbff.GetIPAddress` as the end-user IP address if the feature is enabled and the `Sb-Forwarded-For` header contains a value value. Similarly, Auth will use the end user IP address as determined by `sbff.GetIPAddress` as the rate limiting key under the same circumstances. If the feature is not enabled or the `Sb-Forwarded-For` header is absent or otherwise invalid, Auth will default to existing/legacy behavior.
The goal here is to limit the conditions which resolver implementations can affect the determinism of our DNS checks, without allowing transient DNS failures to block signups: * Reject single label email domains (`a@a`, `a@gmail`) * Use absolute FQDN for DNS lookups to avoid implicit search behavior * Preserves the RFC 5321 fallback, but narrows when it is called * Add an allow list for major email providers to lower latency * Reject mutated display name address that the mail parser might accept * Add test coverage for some corner cases Co-authored-by: Chris Stockton <[email protected]>
Note: this PR depends on #2304 ## Update to Go v1.25.5 As part of this upgrade several changes were needed to resolve go vet failures around non-constant format strings: - Updating all apierrors constructors to use const fmt strings with args - Removing fmt.Sprintf usages that violate go vet fmt checks - Refactoring internal error/message helpers to accept fmt + params In addition stricter checks in the standard library for x509 certificate creation required a change to a SAML test in internal/conf. Now I start with a valid certificate and then set the serial number to an invalid value. To do this I opted for a small refactor to PopulateFields to return the cert object instead of copying the code within the test. ## Why update? Aside from security related reasons and general best practices here are some highlights im looking forward to! * The [flight recorder](https://go.dev/blog/flight-recorder) could be great for debugging performance bottlenecks. I personally am super excited for this feature, I hope the new streamable tracing API will enable a new class of interesting visual tools in the future. * The [synctest](https://pkg.go.dev/testing/synctest) package means no more DI for `now func() time.Time` :D * Addition of [t.Context()](https://pkg.go.dev/testing#T.Context) and [t.Cleanup(func())](https://pkg.go.dev/testing#T.Cleanup) will make lower friction as we sever ties with our testing framework. There are other neat API's like `T.Attr` and `T.Output`. * The new [json/v2](https://pkg.go.dev/encoding/json/[email protected]) package offers more efficient memory usage and faster API's. When I've ran profiling in the past JSON is a significant portion of our CPU time so we should see some nice gains for this. * The new [jsontext](https://pkg.go.dev/encoding/json/[email protected]#example-package-StringReplace) may come in handy for implementing JWT templates depending on how we want to design it. * And much more! --------- Co-authored-by: Chris Stockton <[email protected]>
…2298) ## Problem Fixes #2285 The OAuth 2.0 Client Registration endpoin was incorrectly rejecting custom URI schemes like `cursor://`, or `myapp://`, blocking native application integrations. ## Root Cause The validation logic in `validateRedirectURI()` was overly restrictive, only allowing HTTPS or HTTP (localhost). This contradicted with **RFC 8252** (OAuth 2.0 for Native Apps) - recommends custom URI schemes ## Solution Relaxed redirect URI validation ### New Validation Rules - **HTTPS** - always allowed - **Custom URI schemes** - allowed for native apps (`cursor://`, `myapp://`, `vscode://`, etc.) - **HTTP** - only for localhost/loopback (`localhost`, `127.0.0.1`, `::1`) - **Fragments** - still rejected per spec
Bumps Go version to 1.25.5 in docker to match `go.mod`
Pull Request Test Coverage Report for Build 20844809815Details
💛 - Coveralls |
hf
approved these changes
Jan 9, 2026
hf
requested changes
Jan 12, 2026
Contributor
hf
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has too many commits???
Contributor
|
Ah nvm. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
fix: add issuer validation