* API OTP Context * Update api.go * token * token * fix per discord * copyright header * remove check for token in OTP * Update auth.go * simplify * Update api.gotags/v1.9.0-rc1
} | } | ||||
return nil, false | return nil, false | ||||
} | } | ||||
} else { | |||||
ctx.Data["IsApiToken"] = true | |||||
} | } | ||||
ctx.Data["IsApiToken"] = true | |||||
return u, true | return u, true | ||||
} | } | ||||
} | } |
} | } | ||||
} | } | ||||
// CheckForOTP validateds OTP | |||||
func (ctx *APIContext) CheckForOTP() { | |||||
otpHeader := ctx.Req.Header.Get("X-Gitea-OTP") | |||||
twofa, err := models.GetTwoFactorByUID(ctx.Context.User.ID) | |||||
if err != nil { | |||||
if models.IsErrTwoFactorNotEnrolled(err) { | |||||
return // No 2FA enrollment for this user | |||||
} | |||||
ctx.Context.Error(500) | |||||
return | |||||
} | |||||
ok, err := twofa.ValidateTOTP(otpHeader) | |||||
if err != nil { | |||||
ctx.Context.Error(500) | |||||
return | |||||
} | |||||
if !ok { | |||||
ctx.Context.Error(401) | |||||
return | |||||
} | |||||
} | |||||
// APIContexter returns apicontext as macaron middleware | // APIContexter returns apicontext as macaron middleware | ||||
func APIContexter() macaron.Handler { | func APIContexter() macaron.Handler { | ||||
return func(c *Context) { | return func(c *Context) { |
// Copyright 2014 The Gogs Authors. All rights reserved. | // Copyright 2014 The Gogs Authors. All rights reserved. | ||||
// Copyright 2019 The Gitea Authors. All rights reserved. | |||||
// Use of this source code is governed by a MIT-style | // Use of this source code is governed by a MIT-style | ||||
// license that can be found in the LICENSE file. | // license that can be found in the LICENSE file. | ||||
package context | package context | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/models" | |||||
"code.gitea.io/gitea/modules/auth" | "code.gitea.io/gitea/modules/auth" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
ctx.HTML(200, "user/auth/activate") | ctx.HTML(200, "user/auth/activate") | ||||
return | return | ||||
} | } | ||||
if ctx.IsSigned && auth.IsAPIPath(ctx.Req.URL.Path) && ctx.IsBasicAuth { | |||||
twofa, err := models.GetTwoFactorByUID(ctx.User.ID) | |||||
if err != nil { | |||||
if models.IsErrTwoFactorNotEnrolled(err) { | |||||
return // No 2FA enrollment for this user | |||||
} | |||||
ctx.Error(500) | |||||
return | |||||
} | |||||
otpHeader := ctx.Req.Header.Get("X-Gitea-OTP") | |||||
ok, err := twofa.ValidateTOTP(otpHeader) | |||||
if err != nil { | |||||
ctx.Error(500) | |||||
return | |||||
} | |||||
if !ok { | |||||
ctx.JSON(403, map[string]string{ | |||||
"message": "Only signed in user is allowed to call APIs.", | |||||
}) | |||||
return | |||||
} | |||||
} | |||||
} | } | ||||
// Redirect to log in page if auto-signin info is provided and has not signed in. | // Redirect to log in page if auto-signin info is provided and has not signed in. |
if true == ctx.Data["IsApiToken"] { | if true == ctx.Data["IsApiToken"] { | ||||
return | return | ||||
} | } | ||||
if ctx.Context.IsBasicAuth { | |||||
ctx.CheckForOTP() | |||||
return | |||||
} | |||||
if ctx.IsSigned { | if ctx.IsSigned { | ||||
ctx.RequireCSRF() | ctx.RequireCSRF() | ||||
return | return | ||||
} | } | ||||
func reqBasicAuth() macaron.Handler { | func reqBasicAuth() macaron.Handler { | ||||
return func(ctx *context.Context) { | |||||
if !ctx.IsBasicAuth { | |||||
ctx.Error(401) | |||||
return func(ctx *context.APIContext) { | |||||
if !ctx.Context.IsBasicAuth { | |||||
ctx.Context.Error(401) | |||||
return | return | ||||
} | } | ||||
ctx.CheckForOTP() | |||||
} | } | ||||
} | } | ||||