mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-01 09:34:58 +02:00
chore: drop "oidc_wellknown" tmpl, use json directly (#38731)
`testOAuth2WellKnown` already covers the endpoint's response.
This commit is contained in:
@@ -22,9 +22,6 @@ insert_final_newline = false
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
|
||||
[templates/user/auth/oidc_wellknown.tmpl]
|
||||
indent_style = space
|
||||
|
||||
[templates/shared/actions/runner_badge_*.tmpl]
|
||||
# editconfig lint requires these XML-like files to have charset defined, but the files don't have.
|
||||
charset = unset
|
||||
|
||||
@@ -472,20 +472,6 @@ func GrantApplicationOAuth(ctx *context.Context) {
|
||||
ctx.Redirect(redirect.String(), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// OIDCWellKnown generates JSON so OIDC clients know Gitea's capabilities
|
||||
func OIDCWellKnown(ctx *context.Context) {
|
||||
if !setting.OAuth2.Enabled {
|
||||
http.NotFound(ctx.Resp, ctx.Req)
|
||||
return
|
||||
}
|
||||
jwtRegisteredClaims := oauth2_provider.NewJwtRegisteredClaimsFromUser("well-known", 0, nil)
|
||||
ctx.Data["OidcIssuer"] = jwtRegisteredClaims.Issuer // use the consistent issuer from the JWT registered claims
|
||||
ctx.Data["OidcBaseUrl"] = strings.TrimSuffix(setting.AppURL, "/")
|
||||
ctx.Data["SigningKeyMethodAlg"] = oauth2_provider.DefaultSigningKey.SigningMethod().Alg()
|
||||
// FIXME: no need to use a Golang template to render JSON, just build the JSON response directly in the future
|
||||
ctx.JSONTemplate("user/auth/oidc_wellknown")
|
||||
}
|
||||
|
||||
// OIDCKeys generates the JSON Web Key Set
|
||||
func OIDCKeys(ctx *context.Context) {
|
||||
jwk, err := oauth2_provider.DefaultSigningKey.ToJWK()
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/services/context"
|
||||
"gitea.dev/services/oauth2_provider"
|
||||
)
|
||||
|
||||
// OIDCWellKnown generates JSON so OIDC clients know Gitea's capabilities
|
||||
func OIDCWellKnown(ctx *context.Context) {
|
||||
if !setting.OAuth2.Enabled {
|
||||
http.NotFound(ctx.Resp, ctx.Req)
|
||||
return
|
||||
}
|
||||
jwtRegisteredClaims := oauth2_provider.NewJwtRegisteredClaimsFromUser("well-known", 0, nil)
|
||||
oidcIssuer := jwtRegisteredClaims.Issuer // use the consistent issuer from the JWT registered claims
|
||||
oidcBaseUrl := strings.TrimSuffix(setting.AppURL, "/")
|
||||
|
||||
m := map[string]any{
|
||||
"issuer": oidcIssuer,
|
||||
"authorization_endpoint": oidcBaseUrl + "/login/oauth/authorize",
|
||||
"token_endpoint": oidcBaseUrl + "/login/oauth/access_token",
|
||||
"jwks_uri": oidcBaseUrl + "/login/oauth/keys",
|
||||
"userinfo_endpoint": oidcBaseUrl + "/login/oauth/userinfo",
|
||||
"introspection_endpoint": oidcBaseUrl + "/login/oauth/introspect",
|
||||
"response_types_supported": []string{
|
||||
"code",
|
||||
"id_token",
|
||||
},
|
||||
"id_token_signing_alg_values_supported": []string{
|
||||
oauth2_provider.DefaultSigningKey.SigningMethod().Alg(),
|
||||
},
|
||||
"subject_types_supported": []string{
|
||||
"public",
|
||||
},
|
||||
"scopes_supported": oauth2_provider.GeneralScopesSupported(),
|
||||
"claims_supported": []string{
|
||||
"aud",
|
||||
"exp",
|
||||
"iat",
|
||||
"iss",
|
||||
"sub",
|
||||
"name",
|
||||
"preferred_username",
|
||||
"profile",
|
||||
"picture",
|
||||
"website",
|
||||
"locale",
|
||||
"updated_at",
|
||||
"email",
|
||||
"email_verified",
|
||||
"groups",
|
||||
},
|
||||
"code_challenge_methods_supported": []string{
|
||||
"plain",
|
||||
"S256",
|
||||
},
|
||||
"grant_types_supported": []string{
|
||||
"authorization_code",
|
||||
"refresh_token",
|
||||
},
|
||||
}
|
||||
ctx.JSON(http.StatusOK, m)
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func (b *Base) HTTPError(status int, contents ...string) {
|
||||
func (b *Base) JSON(status int, content any) {
|
||||
b.Resp.Header().Set("Content-Type", "application/json;charset=utf-8")
|
||||
b.Resp.WriteHeader(status)
|
||||
if err := json.NewEncoder(b.Resp).Encode(content); err != nil {
|
||||
if err := json.MarshalWrite(b.Resp, content); err != nil {
|
||||
log.Error("Render JSON failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,20 +104,6 @@ func (ctx *Context) HTML(status int, name templates.TplName) {
|
||||
}
|
||||
}
|
||||
|
||||
// JSONTemplate renders the template as JSON response
|
||||
// keep in mind that the template is processed in HTML context, so JSON things should be handled carefully, e.g.: use JSEscape
|
||||
func (ctx *Context) JSONTemplate(tmpl templates.TplName) {
|
||||
t, err := ctx.Render.TemplateLookup(string(tmpl), nil)
|
||||
if err != nil {
|
||||
ctx.ServerError("unable to find template", err)
|
||||
return
|
||||
}
|
||||
ctx.Resp.Header().Set("Content-Type", "application/json")
|
||||
if err = t.Execute(ctx.Resp, ctx.Data); err != nil {
|
||||
ctx.ServerError("unable to execute template", err)
|
||||
}
|
||||
}
|
||||
|
||||
// RenderToHTML renders the template content to a HTML string
|
||||
func (ctx *Context) RenderToHTML(name templates.TplName, data any) (template.HTML, error) {
|
||||
var buf strings.Builder
|
||||
|
||||
@@ -360,7 +360,7 @@ func UploadHandler(ctx *context.Context) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Error("Unable to check if LFS OID[%s] stat. Error: %v", p.Oid, err)
|
||||
log.Error("Unable to check LFS OID[%s] stat. Error: %v", p.Oid, err)
|
||||
return err
|
||||
}
|
||||
_, err = git_model.NewLFSMetaObject(ctx, repository.ID, p)
|
||||
@@ -378,10 +378,10 @@ func UploadHandler(ctx *context.Context) {
|
||||
}
|
||||
// Do not remove the LFS MetaObject here: this request only creates it after the content is verified and stored,
|
||||
// an invalid request should not remove the existing correct record.
|
||||
// If two requests are loading (the file is incomplete):
|
||||
// If two requests are uploading (the file is incomplete):
|
||||
// * one will keep writing the file content
|
||||
// * one will fail the verification because it reads an incomplete file, the failure should be just ignore
|
||||
// In the end, the first one will complete the upload and insert a LFS MetaObject record.
|
||||
// * one will fail the verification because it reads an incomplete file, the failure should be just be ignored
|
||||
// In the end, the first one will complete the upload and insert a new LFS MetaObject record.
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -74,16 +74,18 @@ type AccessTokenResponse struct {
|
||||
IDToken string `json:"id_token,omitempty"`
|
||||
}
|
||||
|
||||
// GrantAdditionalScopes returns valid scopes coming from grant
|
||||
func GrantAdditionalScopes(grantScopes string) auth.AccessTokenScope {
|
||||
// scopes_supported from templates/user/auth/oidc_wellknown.tmpl
|
||||
generalScopesSupported := []string{
|
||||
func GeneralScopesSupported() []string {
|
||||
return []string{
|
||||
"openid",
|
||||
"profile",
|
||||
"email",
|
||||
"groups",
|
||||
}
|
||||
}
|
||||
|
||||
// GrantAdditionalScopes returns valid scopes coming from grant
|
||||
func GrantAdditionalScopes(grantScopes string) auth.AccessTokenScope {
|
||||
generalScopesSupported := GeneralScopesSupported()
|
||||
var accessScopes []string // the scopes for access control, but not for general information
|
||||
for scope := range strings.SplitSeq(grantScopes, " ") {
|
||||
if scope != "" && !slices.Contains(generalScopesSupported, scope) {
|
||||
|
||||
@@ -26,7 +26,6 @@ export default {
|
||||
prefix: 'tw-',
|
||||
important: true, // the frameworks are mixed together, so tailwind needs to override other framework's styles
|
||||
content: [
|
||||
'!./templates/user/auth/oidc_wellknown.tmpl',
|
||||
'!**/*_test.go',
|
||||
'./{build,models,modules,routers,services}/**/*.go',
|
||||
'./templates/**/*.tmpl',
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"issuer": "{{.OidcIssuer}}",
|
||||
"authorization_endpoint": "{{.OidcBaseUrl}}/login/oauth/authorize",
|
||||
"token_endpoint": "{{.OidcBaseUrl}}/login/oauth/access_token",
|
||||
"jwks_uri": "{{.OidcBaseUrl}}/login/oauth/keys",
|
||||
"userinfo_endpoint": "{{.OidcBaseUrl}}/login/oauth/userinfo",
|
||||
"introspection_endpoint": "{{.OidcBaseUrl}}/login/oauth/introspect",
|
||||
"response_types_supported": [
|
||||
"code",
|
||||
"id_token"
|
||||
],
|
||||
"id_token_signing_alg_values_supported": [
|
||||
"{{.SigningKeyMethodAlg}}"
|
||||
],
|
||||
"subject_types_supported": [
|
||||
"public"
|
||||
],
|
||||
"scopes_supported": [
|
||||
"openid",
|
||||
"profile",
|
||||
"email",
|
||||
"groups"
|
||||
],
|
||||
"claims_supported": [
|
||||
"aud",
|
||||
"exp",
|
||||
"iat",
|
||||
"iss",
|
||||
"sub",
|
||||
"name",
|
||||
"preferred_username",
|
||||
"profile",
|
||||
"picture",
|
||||
"website",
|
||||
"locale",
|
||||
"updated_at",
|
||||
"email",
|
||||
"email_verified",
|
||||
"groups"
|
||||
],
|
||||
"code_challenge_methods_supported": [
|
||||
"plain",
|
||||
"S256"
|
||||
],
|
||||
"grant_types_supported": [
|
||||
"authorization_code",
|
||||
"refresh_token"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user