reprogl

Форк
0
/
provider.go 
141 строка · 2.9 Кб
1
package oauth
2

3
import (
4
	"context"
5
	"errors"
6
	"io"
7
	"log"
8
	"net/http"
9
	"strconv"
10
	"time"
11

12
	"golang.org/x/oauth2"
13
	"golang.org/x/oauth2/yandex"
14
	"xelbot.com/reprogl/container"
15
)
16

17
var (
18
	ProviderNotFound = errors.New("oauth: no matching provider found")
19
	logger           *log.Logger
20
)
21

22
const (
23
	yandexProvider = "yandex"
24
	vkProvider     = "vkontakte"
25
)
26

27
func SetLogger(l *log.Logger) {
28
	logger = l
29
}
30

31
func SupportedProvider(name string) (found bool) {
32
	switch name {
33
	case yandexProvider:
34
		found = true
35
	case vkProvider:
36
		found = true
37
	}
38

39
	return
40
}
41

42
func ConfigByProvider(name string) (*oauth2.Config, error) {
43
	cnf := container.GetConfig()
44
	url := container.GenerateAbsoluteURL("oauth-verification", "provider", name)
45

46
	switch name {
47
	case yandexProvider:
48
		return &oauth2.Config{
49
			ClientID:     cnf.OAuthYandexID,
50
			ClientSecret: cnf.OAuthYandexSecret,
51
			Endpoint:     yandex.Endpoint,
52
			RedirectURL:  url,
53
		}, nil
54
	case vkProvider:
55
		return &oauth2.Config{
56
			ClientID:     cnf.OAuthVkID,
57
			ClientSecret: cnf.OAuthVkSecret,
58
			Endpoint:     vkEndpoint,
59
			RedirectURL:  url,
60
			Scopes:       []string{"vkid.personal_info", "email"},
61
		}, nil
62
	}
63

64
	return nil, ProviderNotFound
65
}
66

67
func AdditionalParams(name string) []string {
68
	params := make([]string, 0)
69
	switch name {
70
	case vkProvider:
71
		return []string{"device_id"}
72
	}
73

74
	return params
75
}
76

77
func UserDataByCode(providerName, code, verifier string, additional map[string]string) (*UserData, error) {
78
	oauthConfig, err := ConfigByProvider(providerName)
79
	if err != nil {
80
		return nil, err
81
	}
82

83
	options := make([]oauth2.AuthCodeOption, 1)
84
	options[0] = oauth2.VerifierOption(verifier)
85

86
	for key, value := range additional {
87
		options = append(options, oauth2.SetAuthURLParam(key, value))
88
	}
89

90
	token, err := oauthConfig.Exchange(context.Background(), code, options...)
91
	if err != nil {
92
		return nil, err
93
	}
94

95
	if tokenScope := token.Extra("scope"); tokenScope != nil {
96
		logger.Printf("[OAUTH] token scope: %s", tokenScope)
97
	}
98

99
	resourceOwner, err := resourceOwnerByProvider(providerName, token)
100
	if err != nil {
101
		return nil, err
102
	}
103

104
	return resourceOwner.GetUserData()
105
}
106

107
func resourceOwnerByProvider(name string, token *oauth2.Token) (ResourceOwnerInterface, error) {
108
	switch name {
109
	case yandexProvider:
110
		return &yandexResourceOwner{accessToken: token.AccessToken}, nil
111
	case vkProvider:
112
		return &vkResourceOwner{accessToken: token.AccessToken}, nil
113
	}
114

115
	return nil, ProviderNotFound
116
}
117

118
func doRequest(request *http.Request) ([]byte, error) {
119
	client := http.Client{
120
		Timeout: 5 * time.Second,
121
	}
122

123
	response, err := client.Do(request)
124
	if err != nil {
125
		return nil, err
126
	}
127

128
	if response.StatusCode != http.StatusOK {
129
		return nil, errors.New("oauth: response status code is " + strconv.Itoa(response.StatusCode))
130
	}
131

132
	defer response.Body.Close()
133
	buf, err := io.ReadAll(response.Body)
134
	if err != nil {
135
		return nil, err
136
	}
137

138
	logger.Printf("[OAUTH] user data: %s", buf)
139

140
	return buf, nil
141
}
142

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.