feat: add baidu support as idp (#438)

* feat: add baidu support as idp

Signed-off-by: Steve0x2a <stevesough@gmail.com>

* fix: add license

Signed-off-by: Steve0x2a <stevesough@gmail.com>
This commit is contained in:
Steve0x2a
2022-01-22 19:36:44 +08:00
committed by GitHub
parent 40aa9a4693
commit 02c06bc93c
7 changed files with 160 additions and 0 deletions

115
idp/baidu.go Normal file
View File

@ -0,0 +1,115 @@
// Copyright 2021 The casbin 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 (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"golang.org/x/oauth2"
)
type BaiduIdProvider struct {
Client *http.Client
Config *oauth2.Config
}
func NewBaiduIdProvider(clientId string, clientSecret string, redirectUrl string) *BaiduIdProvider {
idp := &BaiduIdProvider{}
config := idp.getConfig()
config.ClientID = clientId
config.ClientSecret = clientSecret
config.RedirectURL = redirectUrl
idp.Config = config
return idp
}
func (idp *BaiduIdProvider) SetHttpClient(client *http.Client) {
idp.Client = client
}
func (idp *BaiduIdProvider) getConfig() *oauth2.Config {
var endpoint = oauth2.Endpoint{
AuthURL: "https://openapi.baidu.com/oauth/2.0/authorize",
TokenURL: "https://openapi.baidu.com/oauth/2.0/token",
}
var config = &oauth2.Config{
Scopes: []string{"email"},
Endpoint: endpoint,
}
return config
}
func (idp *BaiduIdProvider) GetToken(code string) (*oauth2.Token, error) {
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, idp.Client)
return idp.Config.Exchange(ctx, code)
}
/*
{
"userid":"2097322476",
"username":"wl19871011",
"realname":"阳光",
"userdetail":"喜欢自由",
"birthday":"1987-01-01",
"marriage":"恋爱",
"sex":"男",
"blood":"O",
"constellation":"射手",
"figure":"小巧",
"education":"大学/专科",
"trade":"计算机/电子产品",
"job":"未知",
"birthday_year":"1987",
"birthday_month":"01",
"birthday_day":"01",
}
*/
type BaiduUserInfo struct {
OpenId string `json:"openid"`
Username string `json:"username"`
Portrait string `json:"portrait"`
}
func (idp *BaiduIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
resp, err := idp.Client.Get(fmt.Sprintf("https://openapi.baidu.com/rest/2.0/passport/users/getInfo?access_token=%s", token.AccessToken))
if err != nil {
return nil, err
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
baiduUser := BaiduUserInfo{}
if err = json.Unmarshal(data, &baiduUser); err != nil {
return nil, err
}
userInfo := UserInfo{
Id: baiduUser.OpenId,
Username: baiduUser.Username,
AvatarUrl: fmt.Sprintf("https://himg.bdimg.com/sys/portrait/item/%s", baiduUser.Portrait),
}
return &userInfo, nil
}

View File

@ -60,6 +60,8 @@ func GetIdProvider(providerType string, clientId string, clientSecret string, re
return NewLarkIdProvider(clientId, clientSecret, redirectUrl) return NewLarkIdProvider(clientId, clientSecret, redirectUrl)
} else if providerType == "GitLab" { } else if providerType == "GitLab" {
return NewGitlabIdProvider(clientId, clientSecret, redirectUrl) return NewGitlabIdProvider(clientId, clientSecret, redirectUrl)
} else if providerType == "Baidu" {
return NewBaiduIdProvider(clientId, clientSecret, redirectUrl)
} else if isGothSupport(providerType) { } else if isGothSupport(providerType) {
return NewGothIdProvider(providerType, clientId, clientSecret, redirectUrl) return NewGothIdProvider(providerType, clientId, clientSecret, redirectUrl)
} }

View File

@ -79,6 +79,7 @@ type User struct {
Wecom string `xorm:"wecom varchar(100)" json:"wecom"` Wecom string `xorm:"wecom varchar(100)" json:"wecom"`
Lark string `xorm:"lark varchar(100)" json:"lark"` Lark string `xorm:"lark varchar(100)" json:"lark"`
Gitlab string `xorm:"gitlab varchar(100)" json:"gitlab"` Gitlab string `xorm:"gitlab varchar(100)" json:"gitlab"`
Baidu string `xorm:"baidu varchar(100)" json:"baidu"`
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"`
Slack string `xorm:"slack varchar(100)" json:"slack"` Slack string `xorm:"slack varchar(100)" json:"slack"`

View File

@ -398,6 +398,7 @@ export function getProviderTypeOptions(category) {
{id: 'WeCom', name: 'WeCom'}, {id: 'WeCom', name: 'WeCom'},
{id: 'Lark', name: 'Lark'}, {id: 'Lark', name: 'Lark'},
{id: 'GitLab', name: 'GitLab'}, {id: 'GitLab', name: 'GitLab'},
{id: 'Baidu', name: 'Baidu'},
{id: 'Apple', name: 'Apple'}, {id: 'Apple', name: 'Apple'},
{id: 'AzureAD', name: 'AzureAD'}, {id: 'AzureAD', name: 'AzureAD'},
{id: 'Slack', name: 'Slack'}, {id: 'Slack', name: 'Slack'},

View File

@ -0,0 +1,32 @@
// Copyright 2021 The casbin 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/baidu.svg`} alt="Sign in with Baidu" style={{width: 24, height: 24}} />;
}
const config = {
text: "Sign in with Baidu",
icon: Icon,
iconFormat: name => `fa fa-${name}`,
style: {background: "#ffffff", color: "#000000"},
activeStyle: {background: "#ededee"},
};
const BaiduLoginButton = createButton(config);
export default BaiduLoginButton;

View File

@ -34,6 +34,7 @@ import LinkedInLoginButton from "./LinkedInLoginButton";
import WeComLoginButton from "./WeComLoginButton"; import WeComLoginButton from "./WeComLoginButton";
import LarkLoginButton from "./LarkLoginButton"; import LarkLoginButton from "./LarkLoginButton";
import GitLabLoginButton from "./GitLabLoginButton"; import GitLabLoginButton from "./GitLabLoginButton";
import BaiduLoginButton from "./BaiduLoginButton";
import AppleLoginButton from "./AppleLoginButton" import AppleLoginButton from "./AppleLoginButton"
import AzureADLoginButton from "./AzureADLoginButton"; import AzureADLoginButton from "./AzureADLoginButton";
import SlackLoginButton from "./SlackLoginButton"; import SlackLoginButton from "./SlackLoginButton";
@ -183,6 +184,8 @@ class LoginPage extends React.Component {
return <LarkLoginButton text={text} align={"center"} /> return <LarkLoginButton text={text} align={"center"} />
} else if (type === "GitLab") { } else if (type === "GitLab") {
return <GitLabLoginButton text={text} align={"center"} /> return <GitLabLoginButton text={text} align={"center"} />
} else if (type === "Baidu") {
return <BaiduLoginButton text={text} align={"center"} />
} else if (type === "Apple") { } else if (type === "Apple") {
return <AppleLoginButton text={text} align={"center"} /> return <AppleLoginButton text={text} align={"center"} />
} else if (type === "AzureAD") { } else if (type === "AzureAD") {

View File

@ -69,6 +69,10 @@ const authInfo = {
scope: "read_user+profile", scope: "read_user+profile",
endpoint: "https://gitlab.com/oauth/authorize", endpoint: "https://gitlab.com/oauth/authorize",
}, },
Baidu: {
scope: "basic",
endpoint: "http://openapi.baidu.com/oauth/2.0/authorize",
},
Apple: { Apple: {
scope: "name%20email", scope: "name%20email",
endpoint: "https://appleid.apple.com/auth/authorize", endpoint: "https://appleid.apple.com/auth/authorize",
@ -227,6 +231,8 @@ export function getAuthUrl(application, provider, method) {
return `${endpoint}?app_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}`; return `${endpoint}?app_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}`;
} else if (provider.type === "GitLab") { } else if (provider.type === "GitLab") {
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}`; return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}`;
} else if (provider.type === "Baidu") {
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}&display=popup`;
} else if (provider.type === "Apple") { } else if (provider.type === "Apple") {
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}&response_mode=form_post`; return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}&response_mode=form_post`;
} else if (provider.type === "AzureAD") { } else if (provider.type === "AzureAD") {