如何在用户电子邮件为私密时使用GitHub实现社交登录?

huangapple go评论88阅读模式
英文:

How to implement social login with GitHub when user email is private?

问题

如何使用GitHub实现社交登录,以便在用户的电子邮件设置为私有时,能够获取用户的私有电子邮件进行身份验证?目前,当用户的电子邮件是公开的时,我能够处理用户登录。

我知道这个问题必须通过 https://api.github.com/user/emails 来解决,但是我还没有找到解决方法。

目前用于通过用户公开电子邮件进行社交登录的代码如下:

package configs

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

type GithubUser struct {
	Email  string `json:"email"`
	Name   string `json:"name"`
	Avatar string `json:"avatar_url"`
}

func GetGithubAccessToken(code string) string {
	clientID := GithubKey()
	clientSecret := GithubSecret()

	requestBodyMap := map[string]string{
		"client_id":     clientID,
		"client_secret": clientSecret,
		"code":          code,
	}
	requestJSON, _ := json.Marshal(requestBodyMap)

	req, reqerr := http.NewRequest("POST", "https://github.com/login/oauth/access_token", bytes.NewBuffer(requestJSON))
	if reqerr != nil {
		log.Panic("Request creation failed")
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json")

	resp, resperr := http.DefaultClient.Do(req)
	if resperr != nil {
		log.Panic("Request failed")
	}

	respbody, _ := ioutil.ReadAll(resp.Body)

	type githubAccessTokenResponse struct {
		AccessToken string `json:"access_token"`
		TokenType   string `json:"token_type"`
		Scope       string `json:"scope"`
	}

	var ghresp githubAccessTokenResponse
	json.Unmarshal(respbody, &ghresp)

	return ghresp.AccessToken
}

func GetGithubData(accessToken string) []byte {
	req, reqerr := http.NewRequest("GET", "https://api.github.com/user", nil)
	if reqerr != nil {
		log.Panic("API Request creation failed")
	}

	authorizationHeaderValue := fmt.Sprintf("token %s", accessToken)
	req.Header.Set("Authorization", authorizationHeaderValue)

	resp, resperr := http.DefaultClient.Do(req)
	if resperr != nil {
		log.Panic("Request failed")
	}

	respbody, _ := ioutil.ReadAll(resp.Body)

	return respbody
}

英文:

How to implement social login with GitHub so that I am able to get private emails of user for authentication if users email is set to private? Currently I am able to process user login when user email is public.

I know it has to be done somehow through https://api.github.com/user/emails but haven't been able to figure it out yet.

Current code for doing the social login through user public email:

package configs
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type GithubUser struct {
Email  string `json:"email"`
Name   string `json:"name"`
Avatar string `json:"avatar_url"`
}
func GetGithubAccessToken(code string) string {
clientID := GithubKey()
clientSecret := GithubSecret()
requestBodyMap := map[string]string{
"client_id":     clientID,
"client_secret": clientSecret,
"code":          code,
}
requestJSON, _ := json.Marshal(requestBodyMap)
req, reqerr := http.NewRequest("POST", "https://github.com/login/oauth/access_token", bytes.NewBuffer(requestJSON))
if reqerr != nil {
log.Panic("Request creation failed")
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
resp, resperr := http.DefaultClient.Do(req)
if resperr != nil {
log.Panic("Request failed")
}
respbody, _ := ioutil.ReadAll(resp.Body)
type githubAccessTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType   string `json:"token_type"`
Scope       string `json:"scope"`
}
var ghresp githubAccessTokenResponse
json.Unmarshal(respbody, &ghresp)
return ghresp.AccessToken
}
func GetGithubData(accessToken string) []byte {
req, reqerr := http.NewRequest("GET", "https://api.github.com/user", nil)
if reqerr != nil {
log.Panic("API Request creation failed")
}
authorizationHeaderValue := fmt.Sprintf("token %s", accessToken)
req.Header.Set("Authorization", authorizationHeaderValue)
resp, resperr := http.DefaultClient.Do(req)
if resperr != nil {
log.Panic("Request failed")
}
respbody, _ := ioutil.ReadAll(resp.Body)
return respbody
}

答案1

得分: 2

我弄清楚了,将答案留在这里,也许可以节省其他人的时间。必须对GetGithubData进行更改并添加一些结构。

对于GetGithubData函数,添加了一个新的请求部分,使用之前用于检索用户电子邮件信息的访问令牌来检索用户的电子邮件。

type GithubData struct {
	UserInfo  UserInfo    `json:"user_info"`
	EmailInfo []EmailInfo `json:"email_info,omitempty"`
}

type UserInfo struct {
	AvatarURL string `json:"avatar_url"`
	Name      string `json:"name"`
	Email     string `json:"email"`
}

type EmailInfo struct {
	Email      string `json:"email"`
	Primary    bool   `json:"primary"`
	Verified   bool   `json:"verified"`
	Visibility string `json:"visibility"`
}

func GetGithubData(accessToken string) ([]byte, error) {
	req, reqerr := http.NewRequest("GET", "https://api.github.com/user", nil)
	if reqerr != nil {
		log.Panic("API Request creation failed")
	}

	authorizationHeaderValue := fmt.Sprintf("token %s", accessToken)
	req.Header.Set("Authorization", authorizationHeaderValue)

	resp, resperr := http.DefaultClient.Do(req)
	if resperr != nil {
		log.Panic("Request failed")
	}

	respbody, _ := ioutil.ReadAll(resp.Body)

	req, reqerr = http.NewRequest("GET", "https://api.github.com/user/emails", nil)
	if reqerr != nil {
		log.Panic("API Request creation failed")
	}

	req.Header.Set("Authorization", authorizationHeaderValue)

	resp, resperr = http.DefaultClient.Do(req)
	if resperr != nil {
		log.Panic("Request failed")
	}

	emailResp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	combinedData := fmt.Sprintf(`{"basic_info": %s, "email_info": %s}`, respbody, emailResp)
	return []byte(combinedData), nil
}
英文:

I figured it out, leaving answer here maybe it saves someones time. Had to make a change to GetGithubData and add some more structs.

To GetGithubData function added the part to make a new request to retrieve the user's emails using the same access token that before to retrieve the user's email information.

type GithubData struct {
UserInfo  UserInfo    `json:"user_info"`
EmailInfo []EmailInfo `json:"email_info,omitempty"`
}
type UserInfo struct {
AvatarURL string `json:"avatar_url"`
Name      string `json:"name"`
Email     string `json:"email"`
}
type EmailInfo struct {
Email      string `json:"email"`
Primary    bool   `json:"primary"`
Verified   bool   `json:"verified"`
Visibility string `json:"visibility"`
}
func GetGithubData(accessToken string) ([]byte, error) {
req, reqerr := http.NewRequest("GET", "https://api.github.com/user", nil)
if reqerr != nil {
log.Panic("API Request creation failed")
}
authorizationHeaderValue := fmt.Sprintf("token %s", accessToken)
req.Header.Set("Authorization", authorizationHeaderValue)
resp, resperr := http.DefaultClient.Do(req)
if resperr != nil {
log.Panic("Request failed")
}
respbody, _ := ioutil.ReadAll(resp.Body)
req, reqerr = http.NewRequest("GET", "https://api.github.com/user/emails", nil)
if reqerr != nil {
log.Panic("API Request creation failed")
}
req.Header.Set("Authorization", authorizationHeaderValue)
resp, resperr = http.DefaultClient.Do(req)
if resperr != nil {
log.Panic("Request failed")
}
emailResp, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
combinedData := fmt.Sprintf(`{"basic_info": %s, "email_info": %s}`, respbody, emailResp)
return []byte(combinedData), nil
}

huangapple
  • 本文由 发表于 2023年3月26日 19:02:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75847321.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定