Skip to content

Commit

Permalink
Merge pull request #5 from supabase/master
Browse files Browse the repository at this point in the history
Merge Down
  • Loading branch information
nickmitchko authored Jun 4, 2024
2 parents 8c3f07a + e3ebffb commit 3c31c4b
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 24 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ on:
push:
branches:
- master
tags: ['*']
tags: ["*"]

jobs:
test:
strategy:
matrix:
go-version: [1.21.x]
go-version: [1.22.x]
runs-on: ubuntu-20.04
services:
postgres:
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21-alpine as build
FROM golang:1.22.3-alpine3.20 as build
ENV GO111MODULE=on
ENV CGO_ENABLED=0
ENV GOOS=linux
Expand All @@ -17,7 +17,7 @@ COPY . /go/src/github.com/supabase/auth
# Make sure you change the RELEASE_VERSION value before publishing an image.
RUN RELEASE_VERSION=unspecified make build

FROM alpine:3.17
FROM alpine:3.20
RUN adduser -D -u 1000 supabase

RUN apk add --no-cache ca-certificates
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

go 1.21.0

toolchain go1.21.6
go 1.22.3
5 changes: 0 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,6 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down Expand Up @@ -729,8 +727,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
Expand All @@ -751,7 +747,6 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
Expand Down
25 changes: 15 additions & 10 deletions internal/api/token_oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type IdTokenGrantParams struct {
Issuer string `json:"issuer"`
}

func (p *IdTokenGrantParams) getProvider(ctx context.Context, config *conf.GlobalConfiguration, r *http.Request) (*oidc.Provider, *conf.OAuthProviderConfiguration, string, []string, error) {
func (p *IdTokenGrantParams) getProvider(ctx context.Context, config *conf.GlobalConfiguration, r *http.Request) (*oidc.Provider, bool, string, []string, error) {
log := observability.GetLogEntry(r).Entry

var cfg *conf.OAuthProviderConfiguration
Expand Down Expand Up @@ -54,7 +54,7 @@ func (p *IdTokenGrantParams) getProvider(ctx context.Context, config *conf.Globa
if issuer == "" || !provider.IsAzureIssuer(issuer) {
detectedIssuer, err := provider.DetectAzureIDTokenIssuer(ctx, p.IdToken)
if err != nil {
return nil, nil, "", nil, badRequestError(ErrorCodeValidationFailed, "Unable to detect issuer in ID token for Azure provider").WithInternalError(err)
return nil, false, "", nil, badRequestError(ErrorCodeValidationFailed, "Unable to detect issuer in ID token for Azure provider").WithInternalError(err)
}
issuer = detectedIssuer
}
Expand Down Expand Up @@ -95,20 +95,25 @@ func (p *IdTokenGrantParams) getProvider(ctx context.Context, config *conf.Globa
}

if !allowed {
return nil, nil, "", nil, badRequestError(ErrorCodeValidationFailed, fmt.Sprintf("Custom OIDC provider %q not allowed", p.Provider))
return nil, false, "", nil, badRequestError(ErrorCodeValidationFailed, fmt.Sprintf("Custom OIDC provider %q not allowed", p.Provider))
}

cfg = &conf.OAuthProviderConfiguration{
Enabled: true,
SkipNonceCheck: false,
}
}

if cfg != nil && !cfg.Enabled {
return nil, nil, "", nil, badRequestError(ErrorCodeProviderDisabled, fmt.Sprintf("Provider (issuer %q) is not enabled", issuer))
if !cfg.Enabled {
return nil, false, "", nil, badRequestError(ErrorCodeProviderDisabled, fmt.Sprintf("Provider (issuer %q) is not enabled", issuer))
}

oidcProvider, err := oidc.NewProvider(ctx, issuer)
if err != nil {
return nil, nil, "", nil, err
return nil, false, "", nil, err
}

return oidcProvider, cfg, providerType, acceptableClientIDs, nil
return oidcProvider, cfg.SkipNonceCheck, providerType, acceptableClientIDs, nil
}

// IdTokenGrant implements the id_token grant type flow
Expand All @@ -131,7 +136,7 @@ func (a *API) IdTokenGrant(ctx context.Context, w http.ResponseWriter, r *http.R
return oauthError("invalid request", "provider or client_id and issuer required")
}

oidcProvider, oauthConfig, providerType, acceptableClientIDs, err := params.getProvider(ctx, config, r)
oidcProvider, skipNonceCheck, providerType, acceptableClientIDs, err := params.getProvider(ctx, config, r)
if err != nil {
return err
}
Expand Down Expand Up @@ -179,10 +184,10 @@ func (a *API) IdTokenGrant(ctx context.Context, w http.ResponseWriter, r *http.R
}

if !correctAudience {
return oauthError("invalid request", "Unacceptable audience in id_token")
return oauthError("invalid request", fmt.Sprintf("Unacceptable audience in id_token: %v", idToken.Audience))
}

if !oauthConfig.SkipNonceCheck {
if !skipNonceCheck {
tokenHasNonce := idToken.Nonce != ""
paramsHasNonce := params.Nonce != ""

Expand Down
69 changes: 69 additions & 0 deletions internal/api/token_oidc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package api

import (
"context"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/supabase/auth/internal/conf"
)

type TokenOIDCTestSuite struct {
suite.Suite
API *API
Config *conf.GlobalConfiguration
}

func TestTokenOIDC(t *testing.T) {
api, config, err := setupAPIForTest()
require.NoError(t, err)

ts := &TokenOIDCTestSuite{
API: api,
Config: config,
}
defer api.db.Close()

suite.Run(t, ts)
}

func SetupTestOIDCProvider(ts *TokenOIDCTestSuite) *httptest.Server {
var server *httptest.Server
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/.well-known/openid-configuration":
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"issuer":"` + server.URL + `","authorization_endpoint":"` + server.URL + `/authorize","token_endpoint":"` + server.URL + `/token","jwks_uri":"` + server.URL + `/jwks"}`))
default:
w.WriteHeader(http.StatusNotFound)
}
}))
return server
}

func (ts *TokenOIDCTestSuite) TestGetProvider() {
server := SetupTestOIDCProvider(ts)
defer server.Close()

params := &IdTokenGrantParams{
IdToken: "test-id-token",
AccessToken: "test-access-token",
Nonce: "test-nonce",
Provider: server.URL,
ClientID: "test-client-id",
Issuer: server.URL,
}

ts.Config.External.AllowedIdTokenIssuers = []string{server.URL}

req := httptest.NewRequest(http.MethodPost, "http://localhost", nil)
oidcProvider, skipNonceCheck, providerType, acceptableClientIds, err := params.getProvider(context.Background(), ts.Config, req)
require.NoError(ts.T(), err)
require.NotNil(ts.T(), oidcProvider)
require.False(ts.T(), skipNonceCheck)
require.Equal(ts.T(), params.Provider, providerType)
require.NotEmpty(ts.T(), acceptableClientIds)
}
8 changes: 6 additions & 2 deletions internal/mailer/mailer.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ type EmailData struct {
func NewMailer(globalConfig *conf.GlobalConfiguration) Mailer {
mail := gomail.NewMessage()

// so that messages are not grouped under each other
mail.SetHeader("Message-ID", fmt.Sprintf("<%s@gotrue-mailer>", uuid.Must(uuid.NewV4()).String()))
mail.SetHeaders(map[string][]string{
// Make the emails explicitly set to be HTML formatted (to cover older email clients)
"Content-Type": {"text/html; charset=utf-8"},
// so that messages are not grouped under each other
"Message-ID": {fmt.Sprintf("<%s@gotrue-mailer>", uuid.Must(uuid.NewV4()).String())},
})

from := mail.FormatAddress(globalConfig.SMTP.AdminEmail, globalConfig.SMTP.SenderName)
u, _ := url.ParseRequestURI(globalConfig.API.ExternalURL)
Expand Down

0 comments on commit 3c31c4b

Please sign in to comment.