mirror of
https://github.com/casdoor/casdoor.git
synced 2025-09-07 02:20:28 +08:00
feat: add casdoor as itself idp support (#578)
Signed-off-by: Steve0x2a <stevesough@gmail.com>
This commit is contained in:
159
idp/casdoor.go
Normal file
159
idp/casdoor.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
// Copyright 2022 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 idp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CasdoorIdProvider struct {
|
||||||
|
Client *http.Client
|
||||||
|
Config *oauth2.Config
|
||||||
|
Host string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCasdoorIdProvider(clientId string, clientSecret string, redirectUrl string, hostUrl string) *CasdoorIdProvider {
|
||||||
|
idp := &CasdoorIdProvider{}
|
||||||
|
config := idp.getConfig(hostUrl)
|
||||||
|
config.ClientID = clientId
|
||||||
|
config.ClientSecret = clientSecret
|
||||||
|
config.RedirectURL = redirectUrl
|
||||||
|
idp.Config = config
|
||||||
|
idp.Host = hostUrl
|
||||||
|
return idp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *CasdoorIdProvider) SetHttpClient(client *http.Client) {
|
||||||
|
idp.Client = client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *CasdoorIdProvider) getConfig(hostUrl string) *oauth2.Config {
|
||||||
|
return &oauth2.Config{
|
||||||
|
Endpoint: oauth2.Endpoint{
|
||||||
|
TokenURL: hostUrl + "/api/login/oauth/access_token",
|
||||||
|
},
|
||||||
|
Scopes: []string{"openid email profile"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type CasdoorToken struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *CasdoorIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||||
|
resp, err := http.PostForm(idp.Config.Endpoint.TokenURL, url.Values{
|
||||||
|
"client_id": {idp.Config.ClientID},
|
||||||
|
"client_secret": {idp.Config.ClientSecret},
|
||||||
|
"code": {code},
|
||||||
|
"grant_type": {"authorization_code"},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pToken := &CasdoorToken{}
|
||||||
|
err = json.Unmarshal(body, pToken)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if token is expired
|
||||||
|
if pToken.ExpiresIn <= 0 {
|
||||||
|
return nil, fmt.Errorf("%s", pToken.AccessToken)
|
||||||
|
}
|
||||||
|
token := &oauth2.Token{
|
||||||
|
AccessToken: pToken.AccessToken,
|
||||||
|
Expiry: time.Unix(time.Now().Unix()+int64(pToken.ExpiresIn), 0),
|
||||||
|
}
|
||||||
|
return token, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"sub": "2f80c349-4beb-407f-b1f0-528aac0f1acd",
|
||||||
|
"iss": "https://door.casbin.com",
|
||||||
|
"aud": "7a11****0fa2172",
|
||||||
|
"name": "admin",
|
||||||
|
"preferred_username": "Admin",
|
||||||
|
"email": "admin@example.com",
|
||||||
|
"picture": "https://casbin.org/img/casbin.svg",
|
||||||
|
"address": "Guangdong",
|
||||||
|
"phone": "12345678910"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
type CasdoorUserInfo struct {
|
||||||
|
Id string `json:"sub"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
DisplayName string `json:"preferred_username"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
AvatarUrl string `json:"picture"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *CasdoorIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
|
cdUserinfo := &CasdoorUserInfo{}
|
||||||
|
accessToken := token.AccessToken
|
||||||
|
request, err := http.NewRequest("GET", fmt.Sprintf("%s/api/userinfo", idp.Host), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
//add accesstoken to bearer token
|
||||||
|
request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
|
||||||
|
resp, err := idp.Client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(data, cdUserinfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cdUserinfo.Status != "" {
|
||||||
|
return nil, fmt.Errorf("err: %s", cdUserinfo.Msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
userInfo := &UserInfo{
|
||||||
|
Id: cdUserinfo.Id,
|
||||||
|
Username: cdUserinfo.Name,
|
||||||
|
DisplayName: cdUserinfo.DisplayName,
|
||||||
|
Email: cdUserinfo.Email,
|
||||||
|
AvatarUrl: cdUserinfo.AvatarUrl,
|
||||||
|
}
|
||||||
|
return userInfo, nil
|
||||||
|
|
||||||
|
}
|
@@ -78,6 +78,8 @@ func GetIdProvider(typ string, subType string, clientId string, clientSecret str
|
|||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
} else if typ == "Casdoor" {
|
||||||
|
return NewCasdoorIdProvider(clientId, clientSecret, redirectUrl, hostUrl)
|
||||||
} else if isGothSupport(typ) {
|
} else if isGothSupport(typ) {
|
||||||
return NewGothIdProvider(typ, clientId, clientSecret, redirectUrl)
|
return NewGothIdProvider(typ, clientId, clientSecret, redirectUrl)
|
||||||
}
|
}
|
||||||
|
@@ -85,6 +85,7 @@ type User struct {
|
|||||||
Gitlab string `xorm:"gitlab varchar(100)" json:"gitlab"`
|
Gitlab string `xorm:"gitlab varchar(100)" json:"gitlab"`
|
||||||
Adfs string `xorm:"adfs varchar(100)" json:"adfs"`
|
Adfs string `xorm:"adfs varchar(100)" json:"adfs"`
|
||||||
Baidu string `xorm:"baidu varchar(100)" json:"baidu"`
|
Baidu string `xorm:"baidu varchar(100)" json:"baidu"`
|
||||||
|
Casdoor string `xorm:"casdoor varchar(100)" json:"casdoor"`
|
||||||
Infoflow string `xorm:"infoflow varchar(100)" json:"infoflow"`
|
Infoflow string `xorm:"infoflow varchar(100)" json:"infoflow"`
|
||||||
Apple string `xorm:"apple varchar(100)" json:"apple"`
|
Apple string `xorm:"apple varchar(100)" json:"apple"`
|
||||||
AzureAD string `xorm:"azuread varchar(100)" json:"azuread"`
|
AzureAD string `xorm:"azuread varchar(100)" json:"azuread"`
|
||||||
|
@@ -478,6 +478,39 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/buy-product": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Product API"
|
||||||
|
],
|
||||||
|
"description": "buy product",
|
||||||
|
"operationId": "ApiController.BuyProduct",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "id",
|
||||||
|
"description": "The id of the product",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "providerName",
|
||||||
|
"description": "The name of the provider",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/check-ldap-users-exist": {
|
"/api/check-ldap-users-exist": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -1710,6 +1743,49 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/get-user-payments": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Payment API"
|
||||||
|
],
|
||||||
|
"description": "get payments for a user",
|
||||||
|
"operationId": "ApiController.GetUserPayments",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "owner",
|
||||||
|
"description": "The owner of payments",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "organization",
|
||||||
|
"description": "The organization of the user",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "user",
|
||||||
|
"description": "The username of the user",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/object.Payment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/get-users": {
|
"/api/get-users": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -1936,6 +2012,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/login/oauth/introspect": {
|
||||||
|
"post": {
|
||||||
|
"description": "The introspection endpoint is an OAuth 2.0 endpoint that takes a",
|
||||||
|
"operationId": "ApiController.IntrospectToken",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "formData",
|
||||||
|
"name": "token",
|
||||||
|
"description": "access_token's value or refresh_token's value",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "formData",
|
||||||
|
"name": "token_type_hint",
|
||||||
|
"description": "the token type access_token or refresh_token",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.IntrospectionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/login/oauth/logout": {
|
"/api/login/oauth/logout": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -2015,7 +2121,6 @@
|
|||||||
"in": "query",
|
"in": "query",
|
||||||
"name": "client_secret",
|
"name": "client_secret",
|
||||||
"description": "OAuth client secret",
|
"description": "OAuth client secret",
|
||||||
"required": true,
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -2046,6 +2151,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/notify-payment": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Payment API"
|
||||||
|
],
|
||||||
|
"description": "notify payment",
|
||||||
|
"operationId": "ApiController.NotifyPayment",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "The details of the payment",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Payment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/send-verification-code": {
|
"/api/send-verification-code": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -2664,11 +2797,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"2015.0xc0000edb90.false": {
|
"2026.0xc000380de0.false": {
|
||||||
"title": "false",
|
"title": "false",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"2049.0xc0000edbc0.false": {
|
"2060.0xc000380e10.false": {
|
||||||
"title": "false",
|
"title": "false",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
@@ -2685,10 +2818,10 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"data": {
|
"data": {
|
||||||
"$ref": "#/definitions/2015.0xc0000edb90.false"
|
"$ref": "#/definitions/2026.0xc000380de0.false"
|
||||||
},
|
},
|
||||||
"data2": {
|
"data2": {
|
||||||
"$ref": "#/definitions/2049.0xc0000edbc0.false"
|
"$ref": "#/definitions/2060.0xc000380e10.false"
|
||||||
},
|
},
|
||||||
"msg": {
|
"msg": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -2709,10 +2842,10 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"data": {
|
"data": {
|
||||||
"$ref": "#/definitions/2015.0xc0000edb90.false"
|
"$ref": "#/definitions/2026.0xc000380de0.false"
|
||||||
},
|
},
|
||||||
"data2": {
|
"data2": {
|
||||||
"$ref": "#/definitions/2049.0xc0000edbc0.false"
|
"$ref": "#/definitions/2060.0xc000380e10.false"
|
||||||
},
|
},
|
||||||
"msg": {
|
"msg": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -2864,6 +2997,12 @@
|
|||||||
"title": "Cert",
|
"title": "Cert",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"authorityPublicKey": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"authorityRootPublicKey": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"bitSize": {
|
"bitSize": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64"
|
"format": "int64"
|
||||||
@@ -2913,6 +3052,54 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"object.IntrospectionResponse": {
|
||||||
|
"title": "IntrospectionResponse",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"active": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"aud": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"client_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"exp": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"iat": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"iss": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"jti": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"nbf": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sub": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"token_type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"object.Organization": {
|
"object.Organization": {
|
||||||
"title": "Organization",
|
"title": "Organization",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -2950,6 +3137,12 @@
|
|||||||
"phonePrefix": {
|
"phonePrefix": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"websiteUrl": {
|
"websiteUrl": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@@ -2959,19 +3152,19 @@
|
|||||||
"title": "Payment",
|
"title": "Payment",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"amount": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"createdTime": {
|
"createdTime": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"currency": {
|
"currency": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"detail": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"displayName": {
|
"displayName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"good": {
|
"message": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
@@ -2983,12 +3176,31 @@
|
|||||||
"owner": {
|
"owner": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"payUrl": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"productDisplayName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"productName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"returnUrl": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@@ -3074,8 +3286,8 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"price": {
|
"price": {
|
||||||
"type": "integer",
|
"type": "number",
|
||||||
"format": "int64"
|
"format": "double"
|
||||||
},
|
},
|
||||||
"providers": {
|
"providers": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@@ -3087,6 +3299,9 @@
|
|||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64"
|
"format": "int64"
|
||||||
},
|
},
|
||||||
|
"returnUrl": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"sold": {
|
"sold": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64"
|
"format": "int64"
|
||||||
@@ -3112,6 +3327,9 @@
|
|||||||
"category": {
|
"category": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"cert": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"clientId": {
|
"clientId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@@ -3482,6 +3700,9 @@
|
|||||||
"birthday": {
|
"birthday": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"casdoor": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdIp": {
|
"createdIp": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@@ -309,6 +309,28 @@ paths:
|
|||||||
description: object
|
description: object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Response'
|
$ref: '#/definitions/Response'
|
||||||
|
/api/buy-product:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Product API
|
||||||
|
description: buy product
|
||||||
|
operationId: ApiController.BuyProduct
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: id
|
||||||
|
description: The id of the product
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: providerName
|
||||||
|
description: The name of the provider
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/check-ldap-users-exist:
|
/api/check-ldap-users-exist:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@@ -1111,6 +1133,35 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: '{int} int The count of filtered users for an organization'
|
description: '{int} int The count of filtered users for an organization'
|
||||||
|
/api/get-user-payments:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Payment API
|
||||||
|
description: get payments for a user
|
||||||
|
operationId: ApiController.GetUserPayments
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: owner
|
||||||
|
description: The owner of payments
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: organization
|
||||||
|
description: The organization of the user
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: user
|
||||||
|
description: The username of the user
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.Payment'
|
||||||
/api/get-users:
|
/api/get-users:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -1262,6 +1313,26 @@ paths:
|
|||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.TokenWrapper'
|
$ref: '#/definitions/object.TokenWrapper'
|
||||||
|
/api/login/oauth/introspect:
|
||||||
|
post:
|
||||||
|
description: The introspection endpoint is an OAuth 2.0 endpoint that takes a
|
||||||
|
operationId: ApiController.IntrospectToken
|
||||||
|
parameters:
|
||||||
|
- in: formData
|
||||||
|
name: token
|
||||||
|
description: access_token's value or refresh_token's value
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: formData
|
||||||
|
name: token_type_hint
|
||||||
|
description: the token type access_token or refresh_token
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.IntrospectionResponse'
|
||||||
/api/login/oauth/logout:
|
/api/login/oauth/logout:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -1318,7 +1389,6 @@ paths:
|
|||||||
- in: query
|
- in: query
|
||||||
name: client_secret
|
name: client_secret
|
||||||
description: OAuth client secret
|
description: OAuth client secret
|
||||||
required: true
|
|
||||||
type: string
|
type: string
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
@@ -1336,6 +1406,24 @@ paths:
|
|||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/controllers.Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
|
/api/notify-payment:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Payment API
|
||||||
|
description: notify payment
|
||||||
|
operationId: ApiController.NotifyPayment
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: The details of the payment
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Payment'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/send-verification-code:
|
/api/send-verification-code:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@@ -1743,10 +1831,10 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.Userinfo'
|
$ref: '#/definitions/object.Userinfo'
|
||||||
definitions:
|
definitions:
|
||||||
2015.0xc0000edb90.false:
|
2026.0xc000380de0.false:
|
||||||
title: "false"
|
title: "false"
|
||||||
type: object
|
type: object
|
||||||
2049.0xc0000edbc0.false:
|
2060.0xc000380e10.false:
|
||||||
title: "false"
|
title: "false"
|
||||||
type: object
|
type: object
|
||||||
RequestForm:
|
RequestForm:
|
||||||
@@ -1760,9 +1848,9 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
$ref: '#/definitions/2015.0xc0000edb90.false'
|
$ref: '#/definitions/2026.0xc000380de0.false'
|
||||||
data2:
|
data2:
|
||||||
$ref: '#/definitions/2049.0xc0000edbc0.false'
|
$ref: '#/definitions/2060.0xc000380e10.false'
|
||||||
msg:
|
msg:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
@@ -1776,9 +1864,9 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
$ref: '#/definitions/2015.0xc0000edb90.false'
|
$ref: '#/definitions/2026.0xc000380de0.false'
|
||||||
data2:
|
data2:
|
||||||
$ref: '#/definitions/2049.0xc0000edbc0.false'
|
$ref: '#/definitions/2060.0xc000380e10.false'
|
||||||
msg:
|
msg:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
@@ -1880,6 +1968,10 @@ definitions:
|
|||||||
title: Cert
|
title: Cert
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
authorityPublicKey:
|
||||||
|
type: string
|
||||||
|
authorityRootPublicKey:
|
||||||
|
type: string
|
||||||
bitSize:
|
bitSize:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
@@ -1912,6 +2004,39 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
value:
|
value:
|
||||||
type: string
|
type: string
|
||||||
|
object.IntrospectionResponse:
|
||||||
|
title: IntrospectionResponse
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
active:
|
||||||
|
type: boolean
|
||||||
|
aud:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
client_id:
|
||||||
|
type: string
|
||||||
|
exp:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
iat:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
iss:
|
||||||
|
type: string
|
||||||
|
jti:
|
||||||
|
type: string
|
||||||
|
nbf:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
scope:
|
||||||
|
type: string
|
||||||
|
sub:
|
||||||
|
type: string
|
||||||
|
token_type:
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
object.Organization:
|
object.Organization:
|
||||||
title: Organization
|
title: Organization
|
||||||
type: object
|
type: object
|
||||||
@@ -1938,21 +2063,25 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
phonePrefix:
|
phonePrefix:
|
||||||
type: string
|
type: string
|
||||||
|
tags:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
websiteUrl:
|
websiteUrl:
|
||||||
type: string
|
type: string
|
||||||
object.Payment:
|
object.Payment:
|
||||||
title: Payment
|
title: Payment
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
amount:
|
|
||||||
type: string
|
|
||||||
createdTime:
|
createdTime:
|
||||||
type: string
|
type: string
|
||||||
currency:
|
currency:
|
||||||
type: string
|
type: string
|
||||||
|
detail:
|
||||||
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
good:
|
message:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
@@ -1960,10 +2089,23 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
owner:
|
owner:
|
||||||
type: string
|
type: string
|
||||||
|
payUrl:
|
||||||
|
type: string
|
||||||
|
price:
|
||||||
|
type: number
|
||||||
|
format: double
|
||||||
|
productDisplayName:
|
||||||
|
type: string
|
||||||
|
productName:
|
||||||
|
type: string
|
||||||
provider:
|
provider:
|
||||||
type: string
|
type: string
|
||||||
|
returnUrl:
|
||||||
|
type: string
|
||||||
state:
|
state:
|
||||||
type: string
|
type: string
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
type:
|
type:
|
||||||
type: string
|
type: string
|
||||||
user:
|
user:
|
||||||
@@ -2021,8 +2163,8 @@ definitions:
|
|||||||
owner:
|
owner:
|
||||||
type: string
|
type: string
|
||||||
price:
|
price:
|
||||||
type: integer
|
type: number
|
||||||
format: int64
|
format: double
|
||||||
providers:
|
providers:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
@@ -2030,6 +2172,8 @@ definitions:
|
|||||||
quantity:
|
quantity:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
returnUrl:
|
||||||
|
type: string
|
||||||
sold:
|
sold:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
@@ -2047,6 +2191,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
category:
|
category:
|
||||||
type: string
|
type: string
|
||||||
|
cert:
|
||||||
|
type: string
|
||||||
clientId:
|
clientId:
|
||||||
type: string
|
type: string
|
||||||
clientId2:
|
clientId2:
|
||||||
@@ -2296,6 +2442,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
birthday:
|
birthday:
|
||||||
type: string
|
type: string
|
||||||
|
casdoor:
|
||||||
|
type: string
|
||||||
createdIp:
|
createdIp:
|
||||||
type: string
|
type: string
|
||||||
createdTime:
|
createdTime:
|
||||||
|
@@ -303,7 +303,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.state.provider.type !== "Adfs" ? null : (
|
this.state.provider.type !== "Adfs" && this.state.provider.type !== "Casdoor" ? null : (
|
||||||
<Row style={{marginTop: '20px'}} >
|
<Row style={{marginTop: '20px'}} >
|
||||||
<Col style={{marginTop: '5px'}} span={2}>
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||||
|
@@ -404,6 +404,7 @@ export function getProviderTypeOptions(category) {
|
|||||||
{id: 'GitLab', name: 'GitLab'},
|
{id: 'GitLab', name: 'GitLab'},
|
||||||
{id: 'Adfs', name: 'Adfs'},
|
{id: 'Adfs', name: 'Adfs'},
|
||||||
{id: 'Baidu', name: 'Baidu'},
|
{id: 'Baidu', name: 'Baidu'},
|
||||||
|
{id: 'Casdoor', name: 'Casdoor'},
|
||||||
{id: 'Infoflow', name: 'Infoflow'},
|
{id: 'Infoflow', name: 'Infoflow'},
|
||||||
{id: 'Apple', name: 'Apple'},
|
{id: 'Apple', name: 'Apple'},
|
||||||
{id: 'AzureAD', name: 'AzureAD'},
|
{id: 'AzureAD', name: 'AzureAD'},
|
||||||
|
32
web/src/auth/CasdoorLoginButton.js
Normal file
32
web/src/auth/CasdoorLoginButton.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
import {createButton} from "react-social-login-buttons";
|
||||||
|
import {StaticBaseUrl} from "../Setting";
|
||||||
|
|
||||||
|
function Icon({ width = 24, height = 24, color }) {
|
||||||
|
return <img src={`${StaticBaseUrl}/buttons/casdoor.svg`} alt="Sign in with Casdoor" style={{width: 24, height: 24}} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
text: "Sign in with Casdoor",
|
||||||
|
icon: Icon,
|
||||||
|
iconFormat: name => `fa fa-${name}`,
|
||||||
|
style: {background: "#ffffff", color: "#000000"},
|
||||||
|
activeStyle: {background: "#ededee"},
|
||||||
|
};
|
||||||
|
|
||||||
|
const CasdoorLoginButton = createButton(config);
|
||||||
|
|
||||||
|
export default CasdoorLoginButton;
|
@@ -36,6 +36,7 @@ import LarkLoginButton from "./LarkLoginButton";
|
|||||||
import GitLabLoginButton from "./GitLabLoginButton";
|
import GitLabLoginButton from "./GitLabLoginButton";
|
||||||
import AdfsLoginButton from "./AdfsLoginButton";
|
import AdfsLoginButton from "./AdfsLoginButton";
|
||||||
import BaiduLoginButton from "./BaiduLoginButton";
|
import BaiduLoginButton from "./BaiduLoginButton";
|
||||||
|
import CasdoorLoginButton from "./CasdoorLoginButton";
|
||||||
import InfoflowLoginButton from "./InfoflowLoginButton";
|
import InfoflowLoginButton from "./InfoflowLoginButton";
|
||||||
import AppleLoginButton from "./AppleLoginButton"
|
import AppleLoginButton from "./AppleLoginButton"
|
||||||
import AzureADLoginButton from "./AzureADLoginButton";
|
import AzureADLoginButton from "./AzureADLoginButton";
|
||||||
@@ -198,6 +199,8 @@ class LoginPage extends React.Component {
|
|||||||
return <GitLabLoginButton text={text} align={"center"} />
|
return <GitLabLoginButton text={text} align={"center"} />
|
||||||
} else if (type === "Adfs") {
|
} else if (type === "Adfs") {
|
||||||
return <AdfsLoginButton text={text} align={"center"} />
|
return <AdfsLoginButton text={text} align={"center"} />
|
||||||
|
} else if (type === "Casdoor") {
|
||||||
|
return <CasdoorLoginButton text={text} align={"center"} />
|
||||||
} else if (type === "Baidu") {
|
} else if (type === "Baidu") {
|
||||||
return <BaiduLoginButton text={text} align={"center"} />
|
return <BaiduLoginButton text={text} align={"center"} />
|
||||||
} else if (type === "Infoflow") {
|
} else if (type === "Infoflow") {
|
||||||
|
@@ -78,6 +78,10 @@ const authInfo = {
|
|||||||
scope: "basic",
|
scope: "basic",
|
||||||
endpoint: "http://openapi.baidu.com/oauth/2.0/authorize",
|
endpoint: "http://openapi.baidu.com/oauth/2.0/authorize",
|
||||||
},
|
},
|
||||||
|
Casdoor: {
|
||||||
|
scope: "openid%20profile%20email",
|
||||||
|
endpoint: "http://example.com",
|
||||||
|
},
|
||||||
Infoflow: {
|
Infoflow: {
|
||||||
endpoint: "https://xpc.im.baidu.com/oauth2/authorize",
|
endpoint: "https://xpc.im.baidu.com/oauth2/authorize",
|
||||||
},
|
},
|
||||||
@@ -283,6 +287,8 @@ export function getAuthUrl(application, provider, method) {
|
|||||||
return `${provider.domain}/adfs/oauth2/authorize?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&nonce=casdoor&scope=openid`;
|
return `${provider.domain}/adfs/oauth2/authorize?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&nonce=casdoor&scope=openid`;
|
||||||
} else if (provider.type === "Baidu") {
|
} else if (provider.type === "Baidu") {
|
||||||
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}&display=popup`;
|
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}&display=popup`;
|
||||||
|
} else if (provider.type === "Casdoor") {
|
||||||
|
return `${provider.domain}/login/oauth/authorize?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}`;
|
||||||
} else if (provider.type === "Infoflow"){
|
} else if (provider.type === "Infoflow"){
|
||||||
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}?state=${state}`
|
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}?state=${state}`
|
||||||
} else if (provider.type === "Apple") {
|
} else if (provider.type === "Apple") {
|
||||||
|
Reference in New Issue
Block a user