From d8d9387ed07e008b52c67955e0b92bfe80337605 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 19 Feb 2024 16:56:54 +0100 Subject: [PATCH] Check redirect URI param in token endpoint --- db.go | 4 ++-- entity.go | 41 +++++++++++++++++++---------------------- oauth2.go | 20 ++++++++++++++++---- schema.sql | 1 + diff --git a/db.go b/db.go index bc159f78daad22db6c26fd5db240afb775ae7f6e..582589e9ca4cc490813609673db187845c634fd3 100644 --- a/db.go +++ b/db.go @@ -237,8 +237,8 @@ } func (db *DB) CreateAuthCode(ctx context.Context, code *AuthCode) error { return db.db.QueryRowContext(ctx, ` - INSERT INTO AuthCode(hash, created_at, user, client, scope) - VALUES (:hash, :created_at, :user, :client, :scope) + INSERT INTO AuthCode(hash, created_at, user, client, scope, redirect_uri) + VALUES (:hash, :created_at, :user, :client, :scope, :redirect_uri) RETURNING id `, entityArgs(code)...).Scan(&code.ID) } diff --git a/entity.go b/entity.go index 8f672e9f766add6f796a231ce369bc461daa0f19..27ba61d7d53092d631c6d0c1b561f62fadcc2674 100644 --- a/entity.go +++ b/entity.go @@ -231,37 +231,34 @@ ExpiresAt time.Time } type AuthCode struct { - ID ID[*AuthCode] - Hash []byte - CreatedAt time.Time - User ID[*User] - Client ID[*Client] - Scope string + ID ID[*AuthCode] + Hash []byte + CreatedAt time.Time + User ID[*User] + Client ID[*Client] + Scope string + RedirectURI string } -func NewAuthCode(user ID[*User], client ID[*Client], scope string) (code *AuthCode, secret string, err error) { +func (code *AuthCode) Generate() (secret string, err error) { secret, hash, err := generateSecret() if err != nil { - return nil, "", fmt.Errorf("failed to generate authentication code secret: %v", err) + return "", fmt.Errorf("failed to generate authentication code secret: %v", err) } - code = &AuthCode{ - Hash: hash, - CreatedAt: time.Now(), - User: user, - Client: client, - Scope: scope, - } - return code, secret, nil + code.Hash = hash + code.CreatedAt = time.Now() + return secret, nil } func (code *AuthCode) columns() map[string]interface{} { return map[string]interface{}{ - "id": &code.ID, - "hash": &code.Hash, - "created_at": &code.CreatedAt, - "user": &code.User, - "client": &code.Client, - "scope": (*nullString)(&code.Scope), + "id": &code.ID, + "hash": &code.Hash, + "created_at": &code.CreatedAt, + "user": &code.User, + "client": &code.Client, + "scope": (*nullString)(&code.Scope), + "redirect_uri": (*nullString)(&code.RedirectURI), } } diff --git a/oauth2.go b/oauth2.go index d9926dd41e38d3b49ee5bc7e83951de823a9a766..df37a6a9a4a00f719714517dce2e1e777bdd9406 100644 --- a/oauth2.go +++ b/oauth2.go @@ -158,13 +158,19 @@ } return } - authCode, secret, err := NewAuthCode(loginToken.User, client.ID, scope) + authCode := AuthCode{ + User: loginToken.User, + Client: client.ID, + Scope: scope, + RedirectURI: rawRedirectURI, + } + secret, err := authCode.Generate() if err != nil { httpError(w, fmt.Errorf("failed to generate authentication code: %v", err)) return } - if err := db.CreateAuthCode(ctx, authCode); err != nil { + if err := db.CreateAuthCode(ctx, &authCode); err != nil { httpError(w, fmt.Errorf("failed to create authentication code: %v", err)) return } @@ -195,6 +201,7 @@ clientID := values.Get("client_id") grantType := oauth2.GrantType(values.Get("grant_type")) scope := values.Get("scope") + redirectURI := values.Get("redirect_uri") authClientID, clientSecret, _ := req.BasicAuth() if clientID == "" && authClientID == "" { @@ -263,8 +270,13 @@ Description: "Invalid scope", }) return } - - // TODO: check redirect_uri + if redirectURI != authCode.RedirectURI { + oauthError(w, &oauth2.Error{ + Code: oauth2.ErrorCodeAccessDenied, + Description: "Invalid redirect URI", + }) + return + } token, secret, err := NewAccessTokenFromAuthCode(authCode) if err != nil { diff --git a/schema.sql b/schema.sql index ef86fea6f774ec2997f3ef1a45b8cfb6daf88c8c..7bfcd417e5110f27559ee62a04fe02f73c3c51e8 100644 --- a/schema.sql +++ b/schema.sql @@ -36,6 +36,7 @@ hash BLOB NOT NULL UNIQUE, created_at datetime NOT NULL, user INTEGER NOT NULL, client INTEGER NOT NULL, + redirect_uri TEXT, scope TEXT, FOREIGN KEY(user) REFERENCES User(id), FOREIGN KEY(client) REFERENCES Client(id) -- 2.48.1