227 lines
6.1 KiB
Go
227 lines
6.1 KiB
Go
// Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/casdoor/casdoor/object"
|
|
)
|
|
|
|
// RevokeConsent revokes a consent record
|
|
// @Title RevokeConsent
|
|
// @Tag Consent API
|
|
// @Description revoke a consent record
|
|
// @Param body body object.ConsentRecord true "The consent object"
|
|
// @Success 200 {object} controllers.Response The Response object
|
|
// @router /revoke-consent [post]
|
|
func (c *ApiController) RevokeConsent() {
|
|
userId := c.GetSessionUsername()
|
|
if userId == "" {
|
|
c.ResponseError(c.T("general:Please login first"))
|
|
return
|
|
}
|
|
|
|
var consent object.ConsentRecord
|
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &consent)
|
|
if err != nil {
|
|
c.ResponseError(err.Error())
|
|
return
|
|
}
|
|
|
|
// Validate that consent.Application is not empty
|
|
if consent.Application == "" {
|
|
c.ResponseError(c.T("general:Application cannot be empty"))
|
|
return
|
|
}
|
|
|
|
// Validate that GrantedScopes is not empty when scope-specific revoke is requested
|
|
if len(consent.GrantedScopes) == 0 {
|
|
c.ResponseError(c.T("general:Granted scopes cannot be empty"))
|
|
return
|
|
}
|
|
|
|
userObj, err := object.GetUser(userId)
|
|
if err != nil {
|
|
c.ResponseError(err.Error())
|
|
return
|
|
}
|
|
if userObj == nil {
|
|
c.ResponseError(c.T("general:The user doesn't exist"))
|
|
return
|
|
}
|
|
|
|
newScopes := []object.ConsentRecord{}
|
|
for _, record := range userObj.ApplicationScopes {
|
|
if record.Application != consent.Application {
|
|
// skip other applications
|
|
newScopes = append(newScopes, record)
|
|
continue
|
|
}
|
|
// revoke specified scopes
|
|
revokeSet := make(map[string]bool)
|
|
for _, s := range consent.GrantedScopes {
|
|
revokeSet[s] = true
|
|
}
|
|
remaining := []string{}
|
|
for _, s := range record.GrantedScopes {
|
|
if !revokeSet[s] {
|
|
remaining = append(remaining, s)
|
|
}
|
|
}
|
|
if len(remaining) > 0 {
|
|
// still have remaining scopes, keep the record and update
|
|
record.GrantedScopes = remaining
|
|
newScopes = append(newScopes, record)
|
|
}
|
|
// otherwise the application authorization is revoked, delete the whole record
|
|
}
|
|
userObj.ApplicationScopes = newScopes
|
|
success, err := object.UpdateUser(userObj.GetId(), userObj, nil, false)
|
|
if err != nil {
|
|
c.ResponseError(err.Error())
|
|
return
|
|
}
|
|
c.ResponseOk(success)
|
|
}
|
|
|
|
// GrantConsent grants consent for an OAuth application and returns authorization code
|
|
// @Title GrantConsent
|
|
// @Tag Consent API
|
|
// @Description grant consent for an OAuth application and get authorization code
|
|
// @Param body body object.ConsentRecord true "The consent object with OAuth parameters"
|
|
// @Success 200 {object} controllers.Response The Response object
|
|
// @router /grant-consent [post]
|
|
func (c *ApiController) GrantConsent() {
|
|
userId := c.GetSessionUsername()
|
|
if userId == "" {
|
|
c.ResponseError(c.T("general:Please login first"))
|
|
return
|
|
}
|
|
|
|
var request struct {
|
|
Application string `json:"application"`
|
|
Scopes []string `json:"grantedScopes"`
|
|
ClientId string `json:"clientId"`
|
|
Provider string `json:"provider"`
|
|
SigninMethod string `json:"signinMethod"`
|
|
ResponseType string `json:"responseType"`
|
|
RedirectUri string `json:"redirectUri"`
|
|
Scope string `json:"scope"`
|
|
State string `json:"state"`
|
|
Nonce string `json:"nonce"`
|
|
Challenge string `json:"challenge"`
|
|
Resource string `json:"resource"`
|
|
}
|
|
|
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
|
|
if err != nil {
|
|
c.ResponseError(err.Error())
|
|
return
|
|
}
|
|
|
|
// Validate application by clientId
|
|
application, err := object.GetApplicationByClientId(request.ClientId)
|
|
if err != nil {
|
|
c.ResponseError(err.Error())
|
|
return
|
|
}
|
|
if application == nil {
|
|
c.ResponseError(c.T("general:Invalid client_id"))
|
|
return
|
|
}
|
|
|
|
// Verify that request.Application matches the application's actual ID
|
|
if request.Application != application.GetId() {
|
|
c.ResponseError(c.T("general:Invalid application"))
|
|
return
|
|
}
|
|
|
|
// Update user's ApplicationScopes
|
|
userObj, err := object.GetUser(userId)
|
|
if err != nil {
|
|
c.ResponseError(err.Error())
|
|
return
|
|
}
|
|
if userObj == nil {
|
|
c.ResponseError(c.T("general:User not found"))
|
|
return
|
|
}
|
|
|
|
appId := application.GetId()
|
|
found := false
|
|
// Insert new scope into existing applicationScopes
|
|
for i, record := range userObj.ApplicationScopes {
|
|
if record.Application == appId {
|
|
existing := make(map[string]bool)
|
|
for _, s := range userObj.ApplicationScopes[i].GrantedScopes {
|
|
existing[s] = true
|
|
}
|
|
for _, s := range request.Scopes {
|
|
if !existing[s] {
|
|
userObj.ApplicationScopes[i].GrantedScopes = append(userObj.ApplicationScopes[i].GrantedScopes, s)
|
|
existing[s] = true
|
|
}
|
|
}
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
// create a new applicationScopes if not found
|
|
if !found {
|
|
uniqueScopes := []string{}
|
|
existing := make(map[string]bool)
|
|
for _, s := range request.Scopes {
|
|
if !existing[s] {
|
|
uniqueScopes = append(uniqueScopes, s)
|
|
existing[s] = true
|
|
}
|
|
}
|
|
userObj.ApplicationScopes = append(userObj.ApplicationScopes, object.ConsentRecord{
|
|
Application: appId,
|
|
GrantedScopes: uniqueScopes,
|
|
})
|
|
}
|
|
|
|
_, err = object.UpdateUser(userObj.GetId(), userObj, []string{"application_scopes"}, false)
|
|
if err != nil {
|
|
c.ResponseError(err.Error())
|
|
return
|
|
}
|
|
|
|
// Now get the OAuth code
|
|
code, err := object.GetOAuthCode(
|
|
userId,
|
|
request.ClientId,
|
|
request.Provider,
|
|
request.SigninMethod,
|
|
request.ResponseType,
|
|
request.RedirectUri,
|
|
request.Scope,
|
|
request.State,
|
|
request.Nonce,
|
|
request.Challenge,
|
|
request.Resource,
|
|
c.Ctx.Request.Host,
|
|
c.GetAcceptLanguage(),
|
|
)
|
|
if err != nil {
|
|
c.ResponseError(err.Error())
|
|
return
|
|
}
|
|
|
|
c.ResponseOk(code.Code)
|
|
}
|