Repository navigation
Expand file tree
/
Copy pathgithub.go
More file actions
144 lines (121 loc) · 4 KB
/
Copy pathgithub.go
File metadata and controls
144 lines (121 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package github
import (
"context"
"fmt"
"io"
"net/http"
"time"
"github.com/ovh/cds/engine/api/authentication"
"github.com/ovh/cds/sdk"
"golang.org/x/oauth2"
)
var _ sdk.AuthDriverWithRedirect = new(authDriver)
var _ sdk.AuthDriverWithSigninStateToken = new(authDriver)
// NewDriver returns a new Github auth driver for given config.
func NewDriver(signupDisabled bool, cdsURL, url, urlAPI, clientID, clientSecret, orga string) sdk.AuthDriver {
return &authDriver{
signupDisabled: signupDisabled,
cdsURL: cdsURL,
url: url,
urlAPI: urlAPI,
clientID: clientID,
clientSecret: clientSecret,
organization: orga,
}
}
type authDriver struct {
signupDisabled bool
cdsURL string
url string
urlAPI string
clientID string
clientSecret string
organization string
}
func (d authDriver) GetManifest() sdk.AuthDriverManifest {
return sdk.AuthDriverManifest{
Type: sdk.ConsumerGithub,
SignupDisabled: d.signupDisabled,
}
}
func (d authDriver) GetSigninURI(signinState sdk.AuthSigninConsumerToken) (sdk.AuthDriverSigningRedirect, error) {
// Generate a new state value for the auth signin request
jws, err := authentication.NewDefaultSigninStateToken(signinState.Origin,
signinState.RedirectURI, signinState.IsFirstConnection)
if err != nil {
return sdk.AuthDriverSigningRedirect{}, err
}
var result = sdk.AuthDriverSigningRedirect{
Method: http.MethodGet,
URL: fmt.Sprintf("%s/login/oauth/authorize?client_id=%s&scope=user&state=%s&redirect_uri=%s", d.url, d.clientID, jws, d.cdsURL+"/auth/callback/github"),
}
return result, nil
}
func (d authDriver) GetSessionDuration() time.Duration {
return time.Hour * 24 * 30 // 1 month session
}
func (d authDriver) CheckSigninRequest(req sdk.AuthConsumerSigninRequest) error {
code, err := req.StringE("code")
if err != nil || code == "" {
return sdk.NewErrorFrom(sdk.ErrWrongRequest, "missing or invalid gitlab code")
}
return nil
}
func (d authDriver) CheckSigninStateToken(req sdk.AuthConsumerSigninRequest) error {
// Check if state is given and if its valid
state, err := req.StringE("state")
if err != nil {
return sdk.NewErrorFrom(sdk.ErrWrongRequest, "missing or invalid state value")
}
return authentication.CheckDefaultSigninStateToken(state)
}
func (d authDriver) GetUserInfo(ctx context.Context, req sdk.AuthConsumerSigninRequest) (sdk.AuthDriverUserInfo, error) {
var info sdk.AuthDriverUserInfo
config := &oauth2.Config{
Endpoint: oauth2.Endpoint{
TokenURL: fmt.Sprintf("%s/login/oauth/access_token", d.url),
},
}
ctx2 := context.WithValue(context.Background(), oauth2.HTTPClient, http.DefaultClient)
t, err := config.Exchange(ctx2, req.String("code"),
oauth2.SetAuthURLParam("client_id", d.clientID),
oauth2.SetAuthURLParam("client_secret", d.clientSecret),
oauth2.SetAuthURLParam("state", req.String("state")),
oauth2.SetAuthURLParam("redirect_uri", d.cdsURL+"/auth/callback/github"),
)
if err != nil {
return info, sdk.WrapError(err, "cannot get github token with given code")
}
request, err := http.NewRequest(http.MethodGet, d.urlAPI+"/user", nil)
if err != nil {
return info, sdk.WithStack(err)
}
request.Header.Set("Authorization", "token "+t.AccessToken)
res, err := http.DefaultClient.Do(request)
if err != nil {
return info, sdk.WithStack(err)
}
if res.StatusCode != 200 {
return info, sdk.NewErrorFrom(sdk.ErrUnknownError, "cannot get current user from github")
}
defer res.Body.Close()
resBody, err := io.ReadAll(res.Body)
if err != nil {
return info, sdk.WithStack(err)
}
var githubUser struct {
ID int `json:"id"`
Login string `json:"login"`
Email string `json:"email"`
Name string `json:"name"`
}
if err := sdk.JSONUnmarshal(resBody, &githubUser); err != nil {
return info, sdk.WithStack(err)
}
info.ExternalID = fmt.Sprintf("%d", githubUser.ID)
info.Username = githubUser.Login
info.Fullname = githubUser.Name
info.Email = githubUser.Email
info.Organization = d.organization
return info, nil
}