Skip to content

Commit 2da8261

Browse files
committed
poc of connecting existing application into edx site with openid
1 parent 6dc2f9a commit 2da8261

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

connect.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package auth_backend
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"net/url"
8+
9+
"golang.org/x/oauth2"
10+
)
11+
12+
// Backend is the main part of auth_backend.
13+
// It stores oauth2.Config, app and edx url configuration
14+
type Backend struct {
15+
conf *oauth2.Config
16+
app_url string
17+
edx_url string
18+
}
19+
20+
// Init to initialize a new backend authentication
21+
func Init(client_id, client_secret, app_url, edx_url string) *Backend {
22+
return &Backend{
23+
conf: &oauth2.Config{
24+
ClientID: client_id,
25+
ClientSecret: client_secret,
26+
RedirectURL: app_url + URL_REDIRECT,
27+
Scopes: Scopes(),
28+
Endpoint: oauth2.Endpoint{
29+
AuthURL: edx_url + URL_AUTHORIZATION,
30+
TokenURL: edx_url + URL_ACCESS_TOKEN,
31+
},
32+
},
33+
app_url: app_url,
34+
edx_url: edx_url,
35+
}
36+
}
37+
38+
// GetAuthorizationURL return authentication url based on given state
39+
func (backend *Backend) GetAuthorizationURL(state string) string {
40+
return backend.conf.AuthCodeURL(state)
41+
}
42+
43+
// Authenticate is callback handler when receiving redirection from edx site after successfully login
44+
func (backend *Backend) Authenticate(receivedState string, values url.Values) (UserInfo, error) {
45+
var user UserInfo
46+
47+
queryState := values.Get("state")
48+
if receivedState != queryState {
49+
return user, fmt.Errorf("Invalid session state: retrieved: %s; Param: %s", receivedState, queryState)
50+
}
51+
52+
code := values.Get("code")
53+
token, err := backend.conf.Exchange(oauth2.NoContext, code)
54+
if err != nil {
55+
return user, err
56+
}
57+
58+
client := backend.conf.Client(oauth2.NoContext, token)
59+
userinfo, err := client.Get(backend.edx_url + URL_USER_INFO)
60+
if err != nil {
61+
return user, err
62+
}
63+
defer userinfo.Body.Close()
64+
65+
data, _ := ioutil.ReadAll(userinfo.Body)
66+
if err := json.Unmarshal(data, &user); err != nil {
67+
return user, err
68+
}
69+
70+
return user, nil
71+
}

constant.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package auth_backend
2+
3+
import (
4+
"crypto/rand"
5+
"encoding/base64"
6+
)
7+
8+
const (
9+
// URL_AUTHORIZATION used to request an authorization
10+
URL_AUTHORIZATION = "/oauth2/authorize"
11+
// URL_ACCESS_TOKEN used to get a new access token
12+
URL_ACCESS_TOKEN = "/oauth2/access_token"
13+
// URL_USER_INFO used to retrieve current user information
14+
URL_USER_INFO = "/oauth2/user_info/"
15+
// URL_REDIRECT used as parameters when requesting an authorization as redirect uri
16+
URL_REDIRECT = "/complete/edx-oidc/"
17+
)
18+
19+
// Scopes return a default scopes for authentication
20+
func Scopes() []string {
21+
return []string{"profile", "email", "openid"}
22+
}
23+
24+
// RandomToken generate a random string that will be used as state
25+
func RandomToken(l int) string {
26+
b := make([]byte, l)
27+
rand.Read(b)
28+
return base64.StdEncoding.EncodeToString(b)
29+
}

user.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package auth_backend
2+
3+
// UserInfo stored user information from user endpoint edx
4+
type UserInfo struct {
5+
TrackingID uint `json:"user_tracking_id"`
6+
Email string `json:"email"`
7+
FamilyName string `json:"family_name"`
8+
GivenName string `json:"given_name"`
9+
Locale string `json:"locale"`
10+
Name string `json:"name'`
11+
Username string `json:"preferred_username"`
12+
Sub string `json:"sub"`
13+
}

0 commit comments

Comments
 (0)