2019-03-08 19:42:50 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2019-03-08 19:42:50 +03:00
2022-08-25 05:31:57 +03:00
package auth_test
2019-03-08 19:42:50 +03:00
import (
"testing"
2022-08-25 05:31:57 +03:00
auth_model "code.gitea.io/gitea/models/auth"
2022-05-20 17:08:52 +03:00
"code.gitea.io/gitea/models/db"
2021-11-12 17:36:47 +03:00
"code.gitea.io/gitea/models/unittest"
2021-09-24 14:32:56 +03:00
2019-03-08 19:42:50 +03:00
"github.com/stretchr/testify/assert"
)
func TestOAuth2Application_GenerateClientSecret ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
app := unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Application { ID : 1 } )
2023-10-14 11:37:24 +03:00
secret , err := app . GenerateClientSecret ( db . DefaultContext )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . True ( t , len ( secret ) > 0 )
2022-08-25 05:31:57 +03:00
unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Application { ID : 1 , ClientSecret : app . ClientSecret } )
2019-03-08 19:42:50 +03:00
}
func BenchmarkOAuth2Application_GenerateClientSecret ( b * testing . B ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( b , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
app := unittest . AssertExistsAndLoadBean ( b , & auth_model . OAuth2Application { ID : 1 } )
2019-03-08 19:42:50 +03:00
for i := 0 ; i < b . N ; i ++ {
2023-10-14 11:37:24 +03:00
_ , _ = app . GenerateClientSecret ( db . DefaultContext )
2019-03-08 19:42:50 +03:00
}
}
func TestOAuth2Application_ContainsRedirectURI ( t * testing . T ) {
2022-08-25 05:31:57 +03:00
app := & auth_model . OAuth2Application {
2019-03-08 19:42:50 +03:00
RedirectURIs : [ ] string { "a" , "b" , "c" } ,
}
assert . True ( t , app . ContainsRedirectURI ( "a" ) )
assert . True ( t , app . ContainsRedirectURI ( "b" ) )
assert . True ( t , app . ContainsRedirectURI ( "c" ) )
assert . False ( t , app . ContainsRedirectURI ( "d" ) )
}
2022-09-29 01:19:55 +03:00
func TestOAuth2Application_ContainsRedirectURI_WithPort ( t * testing . T ) {
app := & auth_model . OAuth2Application {
2022-10-24 10:59:24 +03:00
RedirectURIs : [ ] string { "http://127.0.0.1/" , "http://::1/" , "http://192.168.0.1/" , "http://intranet/" , "https://127.0.0.1/" } ,
ConfidentialClient : false ,
2022-09-29 01:19:55 +03:00
}
// http loopback uris should ignore port
// https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
assert . True ( t , app . ContainsRedirectURI ( "http://127.0.0.1:3456/" ) )
assert . True ( t , app . ContainsRedirectURI ( "http://127.0.0.1/" ) )
assert . True ( t , app . ContainsRedirectURI ( "http://[::1]:3456/" ) )
// not http
assert . False ( t , app . ContainsRedirectURI ( "https://127.0.0.1:3456/" ) )
// not loopback
assert . False ( t , app . ContainsRedirectURI ( "http://192.168.0.1:9954/" ) )
assert . False ( t , app . ContainsRedirectURI ( "http://intranet:3456/" ) )
// unparseable
assert . False ( t , app . ContainsRedirectURI ( ":" ) )
}
2023-08-21 07:15:55 +03:00
func TestOAuth2Application_ContainsRedirect_Slash ( t * testing . T ) {
app := & auth_model . OAuth2Application { RedirectURIs : [ ] string { "http://127.0.0.1" } }
assert . True ( t , app . ContainsRedirectURI ( "http://127.0.0.1" ) )
assert . True ( t , app . ContainsRedirectURI ( "http://127.0.0.1/" ) )
assert . False ( t , app . ContainsRedirectURI ( "http://127.0.0.1/other" ) )
app = & auth_model . OAuth2Application { RedirectURIs : [ ] string { "http://127.0.0.1/" } }
assert . True ( t , app . ContainsRedirectURI ( "http://127.0.0.1" ) )
assert . True ( t , app . ContainsRedirectURI ( "http://127.0.0.1/" ) )
assert . False ( t , app . ContainsRedirectURI ( "http://127.0.0.1/other" ) )
}
2019-03-08 19:42:50 +03:00
func TestOAuth2Application_ValidateClientSecret ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
app := unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Application { ID : 1 } )
2023-10-14 11:37:24 +03:00
secret , err := app . GenerateClientSecret ( db . DefaultContext )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . True ( t , app . ValidateClientSecret ( [ ] byte ( secret ) ) )
assert . False ( t , app . ValidateClientSecret ( [ ] byte ( "fewijfowejgfiowjeoifew" ) ) )
}
func TestGetOAuth2ApplicationByClientID ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
app , err := auth_model . GetOAuth2ApplicationByClientID ( db . DefaultContext , "da7da3ba-9a13-4167-856f-3899de0b0138" )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . Equal ( t , "da7da3ba-9a13-4167-856f-3899de0b0138" , app . ClientID )
2022-08-25 05:31:57 +03:00
app , err = auth_model . GetOAuth2ApplicationByClientID ( db . DefaultContext , "invalid client id" )
2019-03-08 19:42:50 +03:00
assert . Error ( t , err )
assert . Nil ( t , app )
}
func TestCreateOAuth2Application ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
app , err := auth_model . CreateOAuth2Application ( db . DefaultContext , auth_model . CreateOAuth2ApplicationOptions { Name : "newapp" , UserID : 1 } )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . Equal ( t , "newapp" , app . Name )
assert . Len ( t , app . ClientID , 36 )
2022-08-25 05:31:57 +03:00
unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Application { Name : "newapp" } )
2019-03-08 19:42:50 +03:00
}
func TestOAuth2Application_TableName ( t * testing . T ) {
2022-08-25 05:31:57 +03:00
assert . Equal ( t , "oauth2_application" , new ( auth_model . OAuth2Application ) . TableName ( ) )
2019-03-08 19:42:50 +03:00
}
func TestOAuth2Application_GetGrantByUserID ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
app := unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Application { ID : 1 } )
2022-05-20 17:08:52 +03:00
grant , err := app . GetGrantByUserID ( db . DefaultContext , 1 )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . Equal ( t , int64 ( 1 ) , grant . UserID )
2022-05-20 17:08:52 +03:00
grant , err = app . GetGrantByUserID ( db . DefaultContext , 34923458 )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . Nil ( t , grant )
}
func TestOAuth2Application_CreateGrant ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
app := unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Application { ID : 1 } )
2022-05-20 17:08:52 +03:00
grant , err := app . CreateGrant ( db . DefaultContext , 2 , "" )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . NotNil ( t , grant )
assert . Equal ( t , int64 ( 2 ) , grant . UserID )
assert . Equal ( t , int64 ( 1 ) , grant . ApplicationID )
2021-01-01 19:33:27 +03:00
assert . Equal ( t , "" , grant . Scope )
2019-03-08 19:42:50 +03:00
}
//////////////////// Grant
func TestGetOAuth2GrantByID ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
grant , err := auth_model . GetOAuth2GrantByID ( db . DefaultContext , 1 )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . Equal ( t , int64 ( 1 ) , grant . ID )
2022-08-25 05:31:57 +03:00
grant , err = auth_model . GetOAuth2GrantByID ( db . DefaultContext , 34923458 )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . Nil ( t , grant )
}
func TestOAuth2Grant_IncreaseCounter ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
grant := unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Grant { ID : 1 , Counter : 1 } )
2022-05-20 17:08:52 +03:00
assert . NoError ( t , grant . IncreaseCounter ( db . DefaultContext ) )
2019-03-08 19:42:50 +03:00
assert . Equal ( t , int64 ( 2 ) , grant . Counter )
2022-08-25 05:31:57 +03:00
unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Grant { ID : 1 , Counter : 2 } )
2019-03-08 19:42:50 +03:00
}
2021-01-01 19:33:27 +03:00
func TestOAuth2Grant_ScopeContains ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
grant := unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Grant { ID : 1 , Scope : "openid profile" } )
2021-01-01 19:33:27 +03:00
assert . True ( t , grant . ScopeContains ( "openid" ) )
assert . True ( t , grant . ScopeContains ( "profile" ) )
assert . False ( t , grant . ScopeContains ( "profil" ) )
assert . False ( t , grant . ScopeContains ( "profile2" ) )
}
2019-03-08 19:42:50 +03:00
func TestOAuth2Grant_GenerateNewAuthorizationCode ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
grant := unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2Grant { ID : 1 } )
2022-05-20 17:08:52 +03:00
code , err := grant . GenerateNewAuthorizationCode ( db . DefaultContext , "https://example2.com/callback" , "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg" , "S256" )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . NotNil ( t , code )
assert . True ( t , len ( code . Code ) > 32 ) // secret length > 32
}
func TestOAuth2Grant_TableName ( t * testing . T ) {
2022-08-25 05:31:57 +03:00
assert . Equal ( t , "oauth2_grant" , new ( auth_model . OAuth2Grant ) . TableName ( ) )
2019-03-08 19:42:50 +03:00
}
2019-04-17 11:18:16 +03:00
func TestGetOAuth2GrantsByUserID ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
result , err := auth_model . GetOAuth2GrantsByUserID ( db . DefaultContext , 1 )
2019-04-17 11:18:16 +03:00
assert . NoError ( t , err )
assert . Len ( t , result , 1 )
assert . Equal ( t , int64 ( 1 ) , result [ 0 ] . ID )
assert . Equal ( t , result [ 0 ] . ApplicationID , result [ 0 ] . Application . ID )
2022-08-25 05:31:57 +03:00
result , err = auth_model . GetOAuth2GrantsByUserID ( db . DefaultContext , 34134 )
2019-04-17 11:18:16 +03:00
assert . NoError ( t , err )
assert . Empty ( t , result )
}
func TestRevokeOAuth2Grant ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
assert . NoError ( t , auth_model . RevokeOAuth2Grant ( db . DefaultContext , 1 , 1 ) )
unittest . AssertNotExistsBean ( t , & auth_model . OAuth2Grant { ID : 1 , UserID : 1 } )
2019-04-17 11:18:16 +03:00
}
2019-03-08 19:42:50 +03:00
//////////////////// Authorization Code
func TestGetOAuth2AuthorizationByCode ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
code , err := auth_model . GetOAuth2AuthorizationByCode ( db . DefaultContext , "authcode" )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . NotNil ( t , code )
assert . Equal ( t , "authcode" , code . Code )
assert . Equal ( t , int64 ( 1 ) , code . ID )
2022-08-25 05:31:57 +03:00
code , err = auth_model . GetOAuth2AuthorizationByCode ( db . DefaultContext , "does not exist" )
2019-03-08 19:42:50 +03:00
assert . NoError ( t , err )
assert . Nil ( t , code )
}
func TestOAuth2AuthorizationCode_ValidateCodeChallenge ( t * testing . T ) {
// test plain
2022-08-25 05:31:57 +03:00
code := & auth_model . OAuth2AuthorizationCode {
2019-03-08 19:42:50 +03:00
CodeChallengeMethod : "plain" ,
CodeChallenge : "test123" ,
}
assert . True ( t , code . ValidateCodeChallenge ( "test123" ) )
assert . False ( t , code . ValidateCodeChallenge ( "ierwgjoergjio" ) )
// test S256
2022-08-25 05:31:57 +03:00
code = & auth_model . OAuth2AuthorizationCode {
2019-03-08 19:42:50 +03:00
CodeChallengeMethod : "S256" ,
CodeChallenge : "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg" ,
}
assert . True ( t , code . ValidateCodeChallenge ( "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt" ) )
assert . False ( t , code . ValidateCodeChallenge ( "wiogjerogorewngoenrgoiuenorg" ) )
// test unknown
2022-08-25 05:31:57 +03:00
code = & auth_model . OAuth2AuthorizationCode {
2019-03-08 19:42:50 +03:00
CodeChallengeMethod : "monkey" ,
CodeChallenge : "foiwgjioriogeiogjerger" ,
}
assert . False ( t , code . ValidateCodeChallenge ( "foiwgjioriogeiogjerger" ) )
// test no code challenge
2022-08-25 05:31:57 +03:00
code = & auth_model . OAuth2AuthorizationCode {
2019-03-08 19:42:50 +03:00
CodeChallengeMethod : "" ,
CodeChallenge : "foierjiogerogerg" ,
}
assert . True ( t , code . ValidateCodeChallenge ( "" ) )
}
func TestOAuth2AuthorizationCode_GenerateRedirectURI ( t * testing . T ) {
2022-08-25 05:31:57 +03:00
code := & auth_model . OAuth2AuthorizationCode {
2019-03-08 19:42:50 +03:00
RedirectURI : "https://example.com/callback" ,
Code : "thecode" ,
}
redirect , err := code . GenerateRedirectURI ( "thestate" )
assert . NoError ( t , err )
2021-06-07 08:27:09 +03:00
assert . Equal ( t , "https://example.com/callback?code=thecode&state=thestate" , redirect . String ( ) )
2019-03-08 19:42:50 +03:00
redirect , err = code . GenerateRedirectURI ( "" )
assert . NoError ( t , err )
2021-06-07 08:27:09 +03:00
assert . Equal ( t , "https://example.com/callback?code=thecode" , redirect . String ( ) )
2019-03-08 19:42:50 +03:00
}
func TestOAuth2AuthorizationCode_Invalidate ( t * testing . T ) {
2021-11-12 17:36:47 +03:00
assert . NoError ( t , unittest . PrepareTestDatabase ( ) )
2022-08-25 05:31:57 +03:00
code := unittest . AssertExistsAndLoadBean ( t , & auth_model . OAuth2AuthorizationCode { Code : "authcode" } )
2022-05-20 17:08:52 +03:00
assert . NoError ( t , code . Invalidate ( db . DefaultContext ) )
2022-08-25 05:31:57 +03:00
unittest . AssertNotExistsBean ( t , & auth_model . OAuth2AuthorizationCode { Code : "authcode" } )
2019-03-08 19:42:50 +03:00
}
func TestOAuth2AuthorizationCode_TableName ( t * testing . T ) {
2022-08-25 05:31:57 +03:00
assert . Equal ( t , "oauth2_authorization_code" , new ( auth_model . OAuth2AuthorizationCode ) . TableName ( ) )
2019-03-08 19:42:50 +03:00
}