feat: add token logout endpoint (#526)

Signed-off-by: Steve0x2a <stevesough@gmail.com>
This commit is contained in:
Steve0x2a
2022-03-02 20:37:31 +08:00
committed by GitHub
parent 22f5ad06ec
commit 2a0dcd746f
7 changed files with 494 additions and 12 deletions

View File

@ -83,6 +83,7 @@ p, *, *, GET, /api/get-account, *, *
p, *, *, GET, /api/userinfo, *, * p, *, *, GET, /api/userinfo, *, *
p, *, *, POST, /api/login/oauth/access_token, *, * p, *, *, POST, /api/login/oauth/access_token, *, *
p, *, *, POST, /api/login/oauth/refresh_token, *, * p, *, *, POST, /api/login/oauth/refresh_token, *, *
p, *, *, GET, /api/login/oauth/logout, *, *
p, *, *, GET, /api/get-application, *, * p, *, *, GET, /api/get-application, *, *
p, *, *, GET, /api/get-users, *, * p, *, *, GET, /api/get-users, *, *
p, *, *, GET, /api/get-user, *, * p, *, *, GET, /api/get-user, *, *

View File

@ -16,6 +16,7 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"net/http"
"github.com/astaxie/beego/utils/pagination" "github.com/astaxie/beego/utils/pagination"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
@ -186,6 +187,7 @@ func (c *ApiController) GetOAuthToken() {
// RefreshToken // RefreshToken
// @Title RefreshToken // @Title RefreshToken
// @Tag Token API
// @Description refresh OAuth access token // @Description refresh OAuth access token
// @Param grant_type query string true "OAuth grant type" // @Param grant_type query string true "OAuth grant type"
// @Param refresh_token query string true "OAuth refresh token" // @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.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
c.ServeJSON() 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()
}

View File

@ -16,6 +16,7 @@ package object
import ( import (
"fmt" "fmt"
"strings"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
"xorm.io/core" "xorm.io/core"
@ -283,3 +284,15 @@ func DeleteApplication(application *Application) bool {
func (application *Application) GetId() string { func (application *Application) GetId() string {
return fmt.Sprintf("%s/%s", application.Owner, application.Name) 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
}

View File

@ -169,6 +169,25 @@ func DeleteToken(token *Token) bool {
return affected != 0 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 { func GetTokenByAccessToken(accessToken string) *Token {
//Check if the accessToken is in the database //Check if the accessToken is in the database
token := Token{AccessToken: accessToken} token := Token{AccessToken: accessToken}

View File

@ -127,6 +127,7 @@ func initAPI() {
beego.Router("/api/login/oauth/code", &controllers.ApiController{}, "POST:GetOAuthCode") 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/access_token", &controllers.ApiController{}, "POST:GetOAuthToken")
beego.Router("/api/login/oauth/refresh_token", &controllers.ApiController{}, "POST:RefreshToken") 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", &controllers.ApiController{}, "GET:GetRecords")
beego.Router("/api/get-records-filter", &controllers.ApiController{}, "POST:GetRecordsByFilter") beego.Router("/api/get-records-filter", &controllers.ApiController{}, "POST:GetRecordsByFilter")

View File

@ -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": { "/api/add-provider": {
"post": { "post": {
"tags": [ "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": { "/api/delete-provider": {
"post": { "post": {
"tags": [ "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": { "/api/get-provider": {
"get": { "get": {
"tags": [ "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": { "/api/login/oauth/refresh_token": {
"post": { "post": {
"tags": [
"Token API"
],
"description": "refresh OAuth access token", "description": "refresh OAuth access token",
"operationId": "ApiController.RefreshToken", "operationId": "ApiController.RefreshToken",
"parameters": [ "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": { "/api/update-provider": {
"post": { "post": {
"tags": [ "tags": [
@ -2476,11 +2664,11 @@
} }
}, },
"definitions": { "definitions": {
"1867.0xc00029b560.false": { "2015.0xc0000edb90.false": {
"title": "false", "title": "false",
"type": "object" "type": "object"
}, },
"1901.0xc00029b590.false": { "2049.0xc0000edbc0.false": {
"title": "false", "title": "false",
"type": "object" "type": "object"
}, },
@ -2497,10 +2685,10 @@
"type": "object", "type": "object",
"properties": { "properties": {
"data": { "data": {
"$ref": "#/definitions/1867.0xc00029b560.false" "$ref": "#/definitions/2015.0xc0000edb90.false"
}, },
"data2": { "data2": {
"$ref": "#/definitions/1901.0xc00029b590.false" "$ref": "#/definitions/2049.0xc0000edbc0.false"
}, },
"msg": { "msg": {
"type": "string" "type": "string"
@ -2521,10 +2709,10 @@
"type": "object", "type": "object",
"properties": { "properties": {
"data": { "data": {
"$ref": "#/definitions/1867.0xc00029b560.false" "$ref": "#/definitions/2015.0xc0000edb90.false"
}, },
"data2": { "data2": {
"$ref": "#/definitions/1901.0xc00029b590.false" "$ref": "#/definitions/2049.0xc0000edbc0.false"
}, },
"msg": { "msg": {
"type": "string" "type": "string"
@ -2606,6 +2794,12 @@
"forgetUrl": { "forgetUrl": {
"type": "string" "type": "string"
}, },
"grantTypes": {
"type": "array",
"items": {
"type": "string"
}
},
"homepageUrl": { "homepageUrl": {
"type": "string" "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": { "object.Provider": {
"title": "Provider", "title": "Provider",
"type": "object", "type": "object",
@ -3258,6 +3503,9 @@
"facebook": { "facebook": {
"type": "string" "type": "string"
}, },
"firstName": {
"type": "string"
},
"gender": { "gender": {
"type": "string" "type": "string"
}, },
@ -3309,12 +3557,19 @@
"isOnline": { "isOnline": {
"type": "boolean" "type": "boolean"
}, },
"karma": {
"type": "integer",
"format": "int64"
},
"language": { "language": {
"type": "string" "type": "string"
}, },
"lark": { "lark": {
"type": "string" "type": "string"
}, },
"lastName": {
"type": "string"
},
"lastSigninIp": { "lastSigninIp": {
"type": "string" "type": "string"
}, },

View File

@ -112,6 +112,24 @@ paths:
description: The Response object description: The Response object
schema: schema:
$ref: '#/definitions/controllers.Response' $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: /api/add-provider:
post: post:
tags: tags:
@ -396,6 +414,24 @@ paths:
description: The Response object description: The Response object
schema: schema:
$ref: '#/definitions/controllers.Response' $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: /api/delete-provider:
post: post:
tags: tags:
@ -750,6 +786,42 @@ paths:
type: array type: array
items: items:
$ref: '#/definitions/object.Permission' $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: /api/get-provider:
get: get:
tags: tags:
@ -1190,8 +1262,36 @@ paths:
description: The Response object description: The Response object
schema: schema:
$ref: '#/definitions/object.TokenWrapper' $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: /api/login/oauth/refresh_token:
post: post:
tags:
- Token API
description: refresh OAuth access token description: refresh OAuth access token
operationId: ApiController.RefreshToken operationId: ApiController.RefreshToken
parameters: parameters:
@ -1460,6 +1560,29 @@ paths:
description: The Response object description: The Response object
schema: schema:
$ref: '#/definitions/controllers.Response' $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: /api/update-provider:
post: post:
tags: tags:
@ -1620,10 +1743,10 @@ paths:
schema: schema:
$ref: '#/definitions/object.Userinfo' $ref: '#/definitions/object.Userinfo'
definitions: definitions:
1867.0xc00029b560.false: 2015.0xc0000edb90.false:
title: "false" title: "false"
type: object type: object
1901.0xc00029b590.false: 2049.0xc0000edbc0.false:
title: "false" title: "false"
type: object type: object
RequestForm: RequestForm:
@ -1637,9 +1760,9 @@ definitions:
type: object type: object
properties: properties:
data: data:
$ref: '#/definitions/1867.0xc00029b560.false' $ref: '#/definitions/2015.0xc0000edb90.false'
data2: data2:
$ref: '#/definitions/1901.0xc00029b590.false' $ref: '#/definitions/2049.0xc0000edbc0.false'
msg: msg:
type: string type: string
name: name:
@ -1653,9 +1776,9 @@ definitions:
type: object type: object
properties: properties:
data: data:
$ref: '#/definitions/1867.0xc00029b560.false' $ref: '#/definitions/2015.0xc0000edb90.false'
data2: data2:
$ref: '#/definitions/1901.0xc00029b590.false' $ref: '#/definitions/2049.0xc0000edbc0.false'
msg: msg:
type: string type: string
name: name:
@ -1710,6 +1833,10 @@ definitions:
format: int64 format: int64
forgetUrl: forgetUrl:
type: string type: string
grantTypes:
type: array
items:
type: string
homepageUrl: homepageUrl:
type: string type: string
logo: logo:
@ -1875,6 +2002,41 @@ definitions:
type: array type: array
items: items:
type: string 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: object.Provider:
title: Provider title: Provider
type: object type: object
@ -2148,6 +2310,8 @@ definitions:
type: string type: string
facebook: facebook:
type: string type: string
firstName:
type: string
gender: gender:
type: string type: string
gitee: gitee:
@ -2182,10 +2346,15 @@ definitions:
type: boolean type: boolean
isOnline: isOnline:
type: boolean type: boolean
karma:
type: integer
format: int64
language: language:
type: string type: string
lark: lark:
type: string type: string
lastName:
type: string
lastSigninIp: lastSigninIp:
type: string type: string
lastSigninTime: lastSigninTime: