mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-03 04:10:20 +08:00
feat: add token logout endpoint (#526)
Signed-off-by: Steve0x2a <stevesough@gmail.com>
This commit is contained in:
@ -83,6 +83,7 @@ p, *, *, GET, /api/get-account, *, *
|
||||
p, *, *, GET, /api/userinfo, *, *
|
||||
p, *, *, POST, /api/login/oauth/access_token, *, *
|
||||
p, *, *, POST, /api/login/oauth/refresh_token, *, *
|
||||
p, *, *, GET, /api/login/oauth/logout, *, *
|
||||
p, *, *, GET, /api/get-application, *, *
|
||||
p, *, *, GET, /api/get-users, *, *
|
||||
p, *, *, GET, /api/get-user, *, *
|
||||
|
@ -16,6 +16,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
@ -186,6 +187,7 @@ func (c *ApiController) GetOAuthToken() {
|
||||
|
||||
// RefreshToken
|
||||
// @Title RefreshToken
|
||||
// @Tag Token API
|
||||
// @Description refresh OAuth access token
|
||||
// @Param grant_type query string true "OAuth grant type"
|
||||
// @Param refresh_token query string true "OAuth refresh token"
|
||||
@ -205,3 +207,25 @@ func (c *ApiController) RefreshToken() {
|
||||
c.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// TokenLogout
|
||||
// @Title TokenLogout
|
||||
// @Tag Token API
|
||||
// @Description delete token by AccessToken
|
||||
// @Param id_token_hint query string true "id_token_hint"
|
||||
// @Param post_logout_redirect_uri query string false "post_logout_redirect_uri"
|
||||
// @Param state query string true "state"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /login/oauth/logout [get]
|
||||
func (c *ApiController) TokenLogout() {
|
||||
token := c.Input().Get("id_token_hint")
|
||||
flag, application := object.DeleteTokenByAceessToken(token)
|
||||
redirectUri := c.Input().Get("post_logout_redirect_uri")
|
||||
state := c.Input().Get("state")
|
||||
if application != nil && object.CheckRedirectUriValid(application, redirectUri) {
|
||||
c.Ctx.Redirect(http.StatusFound, redirectUri+"?state="+state)
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(flag)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"xorm.io/core"
|
||||
@ -283,3 +284,15 @@ func DeleteApplication(application *Application) bool {
|
||||
func (application *Application) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", application.Owner, application.Name)
|
||||
}
|
||||
|
||||
func CheckRedirectUriValid(application *Application, redirectUri string) bool {
|
||||
var validUri = false
|
||||
for _, tmpUri := range application.RedirectUris {
|
||||
fmt.Println(tmpUri, redirectUri)
|
||||
if strings.Contains(redirectUri, tmpUri) {
|
||||
validUri = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return validUri
|
||||
}
|
||||
|
@ -169,6 +169,25 @@ func DeleteToken(token *Token) bool {
|
||||
return affected != 0
|
||||
}
|
||||
|
||||
func DeleteTokenByAceessToken(accessToken string) (bool, *Application) {
|
||||
token := Token{AccessToken: accessToken}
|
||||
existed, err := adapter.Engine.Get(&token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if !existed {
|
||||
return false, nil
|
||||
}
|
||||
application := getApplication(token.Owner, token.Application)
|
||||
affected, err := adapter.Engine.Where("access_token=?", accessToken).Delete(&Token{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return affected != 0, application
|
||||
}
|
||||
|
||||
func GetTokenByAccessToken(accessToken string) *Token {
|
||||
//Check if the accessToken is in the database
|
||||
token := Token{AccessToken: accessToken}
|
||||
|
@ -127,6 +127,7 @@ func initAPI() {
|
||||
beego.Router("/api/login/oauth/code", &controllers.ApiController{}, "POST:GetOAuthCode")
|
||||
beego.Router("/api/login/oauth/access_token", &controllers.ApiController{}, "POST:GetOAuthToken")
|
||||
beego.Router("/api/login/oauth/refresh_token", &controllers.ApiController{}, "POST:RefreshToken")
|
||||
beego.Router("/api/login/oauth/logout", &controllers.ApiController{}, "GET:TokenLogout")
|
||||
|
||||
beego.Router("/api/get-records", &controllers.ApiController{}, "GET:GetRecords")
|
||||
beego.Router("/api/get-records-filter", &controllers.ApiController{}, "POST:GetRecordsByFilter")
|
||||
|
@ -174,6 +174,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-product": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Product API"
|
||||
],
|
||||
"description": "add product",
|
||||
"operationId": "ApiController.AddProduct",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the product",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Product"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-provider": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@ -614,6 +642,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-product": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Product API"
|
||||
],
|
||||
"description": "delete product",
|
||||
"operationId": "ApiController.DeleteProduct",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the product",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Product"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-provider": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@ -1159,6 +1215,61 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-product": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Product API"
|
||||
],
|
||||
"description": "get product",
|
||||
"operationId": "ApiController.GetProduct",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id of the product",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Product"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-products": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Product API"
|
||||
],
|
||||
"description": "get products",
|
||||
"operationId": "ApiController.GetProducts",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "owner",
|
||||
"description": "The owner of products",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.Product"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-provider": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -1825,8 +1936,50 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/login/oauth/logout": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Token API"
|
||||
],
|
||||
"description": "delete token by AccessToken",
|
||||
"operationId": "ApiController.TokenLogout",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id_token_hint",
|
||||
"description": "id_token_hint",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "post_logout_redirect_uri",
|
||||
"description": "post_logout_redirect_uri",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "state",
|
||||
"description": "state",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/login/oauth/refresh_token": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Token API"
|
||||
],
|
||||
"description": "refresh OAuth access token",
|
||||
"operationId": "ApiController.RefreshToken",
|
||||
"parameters": [
|
||||
@ -2231,6 +2384,41 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-product": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Product API"
|
||||
],
|
||||
"description": "update product",
|
||||
"operationId": "ApiController.UpdateProduct",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id of the product",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the product",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Product"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-provider": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@ -2476,11 +2664,11 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"1867.0xc00029b560.false": {
|
||||
"2015.0xc0000edb90.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
"1901.0xc00029b590.false": {
|
||||
"2049.0xc0000edbc0.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
@ -2497,10 +2685,10 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/1867.0xc00029b560.false"
|
||||
"$ref": "#/definitions/2015.0xc0000edb90.false"
|
||||
},
|
||||
"data2": {
|
||||
"$ref": "#/definitions/1901.0xc00029b590.false"
|
||||
"$ref": "#/definitions/2049.0xc0000edbc0.false"
|
||||
},
|
||||
"msg": {
|
||||
"type": "string"
|
||||
@ -2521,10 +2709,10 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/1867.0xc00029b560.false"
|
||||
"$ref": "#/definitions/2015.0xc0000edb90.false"
|
||||
},
|
||||
"data2": {
|
||||
"$ref": "#/definitions/1901.0xc00029b590.false"
|
||||
"$ref": "#/definitions/2049.0xc0000edbc0.false"
|
||||
},
|
||||
"msg": {
|
||||
"type": "string"
|
||||
@ -2606,6 +2794,12 @@
|
||||
"forgetUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"grantTypes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"homepageUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -2854,6 +3048,57 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Product": {
|
||||
"title": "Product",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"detail": {
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"price": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"providers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"quantity": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"sold": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"state": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Provider": {
|
||||
"title": "Provider",
|
||||
"type": "object",
|
||||
@ -3258,6 +3503,9 @@
|
||||
"facebook": {
|
||||
"type": "string"
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
},
|
||||
"gender": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -3309,12 +3557,19 @@
|
||||
"isOnline": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"karma": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"lark": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastName": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastSigninIp": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -112,6 +112,24 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/add-product:
|
||||
post:
|
||||
tags:
|
||||
- Product API
|
||||
description: add product
|
||||
operationId: ApiController.AddProduct
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the product
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Product'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/add-provider:
|
||||
post:
|
||||
tags:
|
||||
@ -396,6 +414,24 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/delete-product:
|
||||
post:
|
||||
tags:
|
||||
- Product API
|
||||
description: delete product
|
||||
operationId: ApiController.DeleteProduct
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the product
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Product'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/delete-provider:
|
||||
post:
|
||||
tags:
|
||||
@ -750,6 +786,42 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Permission'
|
||||
/api/get-product:
|
||||
get:
|
||||
tags:
|
||||
- Product API
|
||||
description: get product
|
||||
operationId: ApiController.GetProduct
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id of the product
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/object.Product'
|
||||
/api/get-products:
|
||||
get:
|
||||
tags:
|
||||
- Product API
|
||||
description: get products
|
||||
operationId: ApiController.GetProducts
|
||||
parameters:
|
||||
- in: query
|
||||
name: owner
|
||||
description: The owner of products
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Product'
|
||||
/api/get-provider:
|
||||
get:
|
||||
tags:
|
||||
@ -1190,8 +1262,36 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/object.TokenWrapper'
|
||||
/api/login/oauth/logout:
|
||||
get:
|
||||
tags:
|
||||
- Token API
|
||||
description: delete token by AccessToken
|
||||
operationId: ApiController.TokenLogout
|
||||
parameters:
|
||||
- in: query
|
||||
name: id_token_hint
|
||||
description: id_token_hint
|
||||
required: true
|
||||
type: string
|
||||
- in: query
|
||||
name: post_logout_redirect_uri
|
||||
description: post_logout_redirect_uri
|
||||
type: string
|
||||
- in: query
|
||||
name: state
|
||||
description: state
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/login/oauth/refresh_token:
|
||||
post:
|
||||
tags:
|
||||
- Token API
|
||||
description: refresh OAuth access token
|
||||
operationId: ApiController.RefreshToken
|
||||
parameters:
|
||||
@ -1460,6 +1560,29 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/update-product:
|
||||
post:
|
||||
tags:
|
||||
- Product API
|
||||
description: update product
|
||||
operationId: ApiController.UpdateProduct
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id of the product
|
||||
required: true
|
||||
type: string
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the product
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Product'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/update-provider:
|
||||
post:
|
||||
tags:
|
||||
@ -1620,10 +1743,10 @@ paths:
|
||||
schema:
|
||||
$ref: '#/definitions/object.Userinfo'
|
||||
definitions:
|
||||
1867.0xc00029b560.false:
|
||||
2015.0xc0000edb90.false:
|
||||
title: "false"
|
||||
type: object
|
||||
1901.0xc00029b590.false:
|
||||
2049.0xc0000edbc0.false:
|
||||
title: "false"
|
||||
type: object
|
||||
RequestForm:
|
||||
@ -1637,9 +1760,9 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/definitions/1867.0xc00029b560.false'
|
||||
$ref: '#/definitions/2015.0xc0000edb90.false'
|
||||
data2:
|
||||
$ref: '#/definitions/1901.0xc00029b590.false'
|
||||
$ref: '#/definitions/2049.0xc0000edbc0.false'
|
||||
msg:
|
||||
type: string
|
||||
name:
|
||||
@ -1653,9 +1776,9 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/definitions/1867.0xc00029b560.false'
|
||||
$ref: '#/definitions/2015.0xc0000edb90.false'
|
||||
data2:
|
||||
$ref: '#/definitions/1901.0xc00029b590.false'
|
||||
$ref: '#/definitions/2049.0xc0000edbc0.false'
|
||||
msg:
|
||||
type: string
|
||||
name:
|
||||
@ -1710,6 +1833,10 @@ definitions:
|
||||
format: int64
|
||||
forgetUrl:
|
||||
type: string
|
||||
grantTypes:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
homepageUrl:
|
||||
type: string
|
||||
logo:
|
||||
@ -1875,6 +2002,41 @@ definitions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
object.Product:
|
||||
title: Product
|
||||
type: object
|
||||
properties:
|
||||
createdTime:
|
||||
type: string
|
||||
currency:
|
||||
type: string
|
||||
detail:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
image:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
price:
|
||||
type: integer
|
||||
format: int64
|
||||
providers:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
quantity:
|
||||
type: integer
|
||||
format: int64
|
||||
sold:
|
||||
type: integer
|
||||
format: int64
|
||||
state:
|
||||
type: string
|
||||
tag:
|
||||
type: string
|
||||
object.Provider:
|
||||
title: Provider
|
||||
type: object
|
||||
@ -2148,6 +2310,8 @@ definitions:
|
||||
type: string
|
||||
facebook:
|
||||
type: string
|
||||
firstName:
|
||||
type: string
|
||||
gender:
|
||||
type: string
|
||||
gitee:
|
||||
@ -2182,10 +2346,15 @@ definitions:
|
||||
type: boolean
|
||||
isOnline:
|
||||
type: boolean
|
||||
karma:
|
||||
type: integer
|
||||
format: int64
|
||||
language:
|
||||
type: string
|
||||
lark:
|
||||
type: string
|
||||
lastName:
|
||||
type: string
|
||||
lastSigninIp:
|
||||
type: string
|
||||
lastSigninTime:
|
||||
|
Reference in New Issue
Block a user