code.gitea.io/gitea@v1.22.3/models/auth/oauth2_test.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package auth_test 5 6 import ( 7 "testing" 8 9 auth_model "code.gitea.io/gitea/models/auth" 10 "code.gitea.io/gitea/models/db" 11 "code.gitea.io/gitea/models/unittest" 12 13 "github.com/stretchr/testify/assert" 14 ) 15 16 func TestOAuth2Application_GenerateClientSecret(t *testing.T) { 17 assert.NoError(t, unittest.PrepareTestDatabase()) 18 app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) 19 secret, err := app.GenerateClientSecret(db.DefaultContext) 20 assert.NoError(t, err) 21 assert.True(t, len(secret) > 0) 22 unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1, ClientSecret: app.ClientSecret}) 23 } 24 25 func BenchmarkOAuth2Application_GenerateClientSecret(b *testing.B) { 26 assert.NoError(b, unittest.PrepareTestDatabase()) 27 app := unittest.AssertExistsAndLoadBean(b, &auth_model.OAuth2Application{ID: 1}) 28 for i := 0; i < b.N; i++ { 29 _, _ = app.GenerateClientSecret(db.DefaultContext) 30 } 31 } 32 33 func TestOAuth2Application_ContainsRedirectURI(t *testing.T) { 34 app := &auth_model.OAuth2Application{ 35 RedirectURIs: []string{"a", "b", "c"}, 36 } 37 assert.True(t, app.ContainsRedirectURI("a")) 38 assert.True(t, app.ContainsRedirectURI("b")) 39 assert.True(t, app.ContainsRedirectURI("c")) 40 assert.False(t, app.ContainsRedirectURI("d")) 41 } 42 43 func TestOAuth2Application_ContainsRedirectURI_WithPort(t *testing.T) { 44 app := &auth_model.OAuth2Application{ 45 RedirectURIs: []string{"http://127.0.0.1/", "http://::1/", "http://192.168.0.1/", "http://intranet/", "https://127.0.0.1/"}, 46 ConfidentialClient: false, 47 } 48 49 // http loopback uris should ignore port 50 // https://datatracker.ietf.org/doc/html/rfc8252#section-7.3 51 assert.True(t, app.ContainsRedirectURI("http://127.0.0.1:3456/")) 52 assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/")) 53 assert.True(t, app.ContainsRedirectURI("http://[::1]:3456/")) 54 55 // not http 56 assert.False(t, app.ContainsRedirectURI("https://127.0.0.1:3456/")) 57 // not loopback 58 assert.False(t, app.ContainsRedirectURI("http://192.168.0.1:9954/")) 59 assert.False(t, app.ContainsRedirectURI("http://intranet:3456/")) 60 // unparseable 61 assert.False(t, app.ContainsRedirectURI(":")) 62 } 63 64 func TestOAuth2Application_ContainsRedirect_Slash(t *testing.T) { 65 app := &auth_model.OAuth2Application{RedirectURIs: []string{"http://127.0.0.1"}} 66 assert.True(t, app.ContainsRedirectURI("http://127.0.0.1")) 67 assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/")) 68 assert.False(t, app.ContainsRedirectURI("http://127.0.0.1/other")) 69 70 app = &auth_model.OAuth2Application{RedirectURIs: []string{"http://127.0.0.1/"}} 71 assert.True(t, app.ContainsRedirectURI("http://127.0.0.1")) 72 assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/")) 73 assert.False(t, app.ContainsRedirectURI("http://127.0.0.1/other")) 74 } 75 76 func TestOAuth2Application_ValidateClientSecret(t *testing.T) { 77 assert.NoError(t, unittest.PrepareTestDatabase()) 78 app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) 79 secret, err := app.GenerateClientSecret(db.DefaultContext) 80 assert.NoError(t, err) 81 assert.True(t, app.ValidateClientSecret([]byte(secret))) 82 assert.False(t, app.ValidateClientSecret([]byte("fewijfowejgfiowjeoifew"))) 83 } 84 85 func TestGetOAuth2ApplicationByClientID(t *testing.T) { 86 assert.NoError(t, unittest.PrepareTestDatabase()) 87 app, err := auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "da7da3ba-9a13-4167-856f-3899de0b0138") 88 assert.NoError(t, err) 89 assert.Equal(t, "da7da3ba-9a13-4167-856f-3899de0b0138", app.ClientID) 90 91 app, err = auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "invalid client id") 92 assert.Error(t, err) 93 assert.Nil(t, app) 94 } 95 96 func TestCreateOAuth2Application(t *testing.T) { 97 assert.NoError(t, unittest.PrepareTestDatabase()) 98 app, err := auth_model.CreateOAuth2Application(db.DefaultContext, auth_model.CreateOAuth2ApplicationOptions{Name: "newapp", UserID: 1}) 99 assert.NoError(t, err) 100 assert.Equal(t, "newapp", app.Name) 101 assert.Len(t, app.ClientID, 36) 102 unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{Name: "newapp"}) 103 } 104 105 func TestOAuth2Application_TableName(t *testing.T) { 106 assert.Equal(t, "oauth2_application", new(auth_model.OAuth2Application).TableName()) 107 } 108 109 func TestOAuth2Application_GetGrantByUserID(t *testing.T) { 110 assert.NoError(t, unittest.PrepareTestDatabase()) 111 app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) 112 grant, err := app.GetGrantByUserID(db.DefaultContext, 1) 113 assert.NoError(t, err) 114 assert.Equal(t, int64(1), grant.UserID) 115 116 grant, err = app.GetGrantByUserID(db.DefaultContext, 34923458) 117 assert.NoError(t, err) 118 assert.Nil(t, grant) 119 } 120 121 func TestOAuth2Application_CreateGrant(t *testing.T) { 122 assert.NoError(t, unittest.PrepareTestDatabase()) 123 app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) 124 grant, err := app.CreateGrant(db.DefaultContext, 2, "") 125 assert.NoError(t, err) 126 assert.NotNil(t, grant) 127 assert.Equal(t, int64(2), grant.UserID) 128 assert.Equal(t, int64(1), grant.ApplicationID) 129 assert.Equal(t, "", grant.Scope) 130 } 131 132 //////////////////// Grant 133 134 func TestGetOAuth2GrantByID(t *testing.T) { 135 assert.NoError(t, unittest.PrepareTestDatabase()) 136 grant, err := auth_model.GetOAuth2GrantByID(db.DefaultContext, 1) 137 assert.NoError(t, err) 138 assert.Equal(t, int64(1), grant.ID) 139 140 grant, err = auth_model.GetOAuth2GrantByID(db.DefaultContext, 34923458) 141 assert.NoError(t, err) 142 assert.Nil(t, grant) 143 } 144 145 func TestOAuth2Grant_IncreaseCounter(t *testing.T) { 146 assert.NoError(t, unittest.PrepareTestDatabase()) 147 grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1}) 148 assert.NoError(t, grant.IncreaseCounter(db.DefaultContext)) 149 assert.Equal(t, int64(2), grant.Counter) 150 unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 2}) 151 } 152 153 func TestOAuth2Grant_ScopeContains(t *testing.T) { 154 assert.NoError(t, unittest.PrepareTestDatabase()) 155 grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Scope: "openid profile"}) 156 assert.True(t, grant.ScopeContains("openid")) 157 assert.True(t, grant.ScopeContains("profile")) 158 assert.False(t, grant.ScopeContains("profil")) 159 assert.False(t, grant.ScopeContains("profile2")) 160 } 161 162 func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) { 163 assert.NoError(t, unittest.PrepareTestDatabase()) 164 grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1}) 165 code, err := grant.GenerateNewAuthorizationCode(db.DefaultContext, "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256") 166 assert.NoError(t, err) 167 assert.NotNil(t, code) 168 assert.True(t, len(code.Code) > 32) // secret length > 32 169 } 170 171 func TestOAuth2Grant_TableName(t *testing.T) { 172 assert.Equal(t, "oauth2_grant", new(auth_model.OAuth2Grant).TableName()) 173 } 174 175 func TestGetOAuth2GrantsByUserID(t *testing.T) { 176 assert.NoError(t, unittest.PrepareTestDatabase()) 177 result, err := auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 1) 178 assert.NoError(t, err) 179 assert.Len(t, result, 1) 180 assert.Equal(t, int64(1), result[0].ID) 181 assert.Equal(t, result[0].ApplicationID, result[0].Application.ID) 182 183 result, err = auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 34134) 184 assert.NoError(t, err) 185 assert.Empty(t, result) 186 } 187 188 func TestRevokeOAuth2Grant(t *testing.T) { 189 assert.NoError(t, unittest.PrepareTestDatabase()) 190 assert.NoError(t, auth_model.RevokeOAuth2Grant(db.DefaultContext, 1, 1)) 191 unittest.AssertNotExistsBean(t, &auth_model.OAuth2Grant{ID: 1, UserID: 1}) 192 } 193 194 //////////////////// Authorization Code 195 196 func TestGetOAuth2AuthorizationByCode(t *testing.T) { 197 assert.NoError(t, unittest.PrepareTestDatabase()) 198 code, err := auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "authcode") 199 assert.NoError(t, err) 200 assert.NotNil(t, code) 201 assert.Equal(t, "authcode", code.Code) 202 assert.Equal(t, int64(1), code.ID) 203 204 code, err = auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "does not exist") 205 assert.NoError(t, err) 206 assert.Nil(t, code) 207 } 208 209 func TestOAuth2AuthorizationCode_ValidateCodeChallenge(t *testing.T) { 210 // test plain 211 code := &auth_model.OAuth2AuthorizationCode{ 212 CodeChallengeMethod: "plain", 213 CodeChallenge: "test123", 214 } 215 assert.True(t, code.ValidateCodeChallenge("test123")) 216 assert.False(t, code.ValidateCodeChallenge("ierwgjoergjio")) 217 218 // test S256 219 code = &auth_model.OAuth2AuthorizationCode{ 220 CodeChallengeMethod: "S256", 221 CodeChallenge: "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", 222 } 223 assert.True(t, code.ValidateCodeChallenge("N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt")) 224 assert.False(t, code.ValidateCodeChallenge("wiogjerogorewngoenrgoiuenorg")) 225 226 // test unknown 227 code = &auth_model.OAuth2AuthorizationCode{ 228 CodeChallengeMethod: "monkey", 229 CodeChallenge: "foiwgjioriogeiogjerger", 230 } 231 assert.False(t, code.ValidateCodeChallenge("foiwgjioriogeiogjerger")) 232 233 // test no code challenge 234 code = &auth_model.OAuth2AuthorizationCode{ 235 CodeChallengeMethod: "", 236 CodeChallenge: "foierjiogerogerg", 237 } 238 assert.True(t, code.ValidateCodeChallenge("")) 239 } 240 241 func TestOAuth2AuthorizationCode_GenerateRedirectURI(t *testing.T) { 242 code := &auth_model.OAuth2AuthorizationCode{ 243 RedirectURI: "https://example.com/callback", 244 Code: "thecode", 245 } 246 247 redirect, err := code.GenerateRedirectURI("thestate") 248 assert.NoError(t, err) 249 assert.Equal(t, "https://example.com/callback?code=thecode&state=thestate", redirect.String()) 250 251 redirect, err = code.GenerateRedirectURI("") 252 assert.NoError(t, err) 253 assert.Equal(t, "https://example.com/callback?code=thecode", redirect.String()) 254 } 255 256 func TestOAuth2AuthorizationCode_Invalidate(t *testing.T) { 257 assert.NoError(t, unittest.PrepareTestDatabase()) 258 code := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"}) 259 assert.NoError(t, code.Invalidate(db.DefaultContext)) 260 unittest.AssertNotExistsBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"}) 261 } 262 263 func TestOAuth2AuthorizationCode_TableName(t *testing.T) { 264 assert.Equal(t, "oauth2_authorization_code", new(auth_model.OAuth2AuthorizationCode).TableName()) 265 }