Skip to content

Commit 4c6b579

Browse files
authored
Merge pull request bitly#270 from jehiah/fb_provider_270
Facebook auth Provider
2 parents 3a79827 + a076347 commit 4c6b579

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Valid providers are :
3030

3131
* [Google](#google-auth-provider) *default*
3232
* [Azure](#azure-auth-provider)
33+
* [Facebook](#facebook-auth-provider)
3334
* [GitHub](#github-auth-provider)
3435
* [GitLab](#gitlab-auth-provider)
3536
* [LinkedIn](#linkedin-auth-provider)
@@ -87,6 +88,11 @@ Note: The user is checked against the group members list on initial authenticati
8788
The Azure AD auth provider uses `openid` as it default scope. It uses `https://graph.windows.net` as a default protected resource. It call to `https://graph.windows.net/me` to get the email address of the user that logs in.
8889

8990

91+
### Facebook Auth Provider
92+
93+
1. Create a new FB App from <https://developers.facebook.com/>
94+
2. Under FB Login, set your Valid OAuth redirect URIs to `https://internal.yourcompany.com/oauth2/callback`
95+
9096
### GitHub Auth Provider
9197

9298
1. Create a new project: https://github.com/settings/developers

api/api.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package api
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"io/ioutil"
67
"log"
@@ -31,6 +32,24 @@ func Request(req *http.Request) (*simplejson.Json, error) {
3132
return data, nil
3233
}
3334

35+
func RequestJson(req *http.Request, v interface{}) error {
36+
resp, err := http.DefaultClient.Do(req)
37+
if err != nil {
38+
log.Printf("%s %s %s", req.Method, req.URL, err)
39+
return err
40+
}
41+
body, err := ioutil.ReadAll(resp.Body)
42+
resp.Body.Close()
43+
log.Printf("%d %s %s %s", resp.StatusCode, req.Method, req.URL, body)
44+
if err != nil {
45+
return err
46+
}
47+
if resp.StatusCode != 200 {
48+
return fmt.Errorf("got %d %s", resp.StatusCode, body)
49+
}
50+
return json.Unmarshal(body, v)
51+
}
52+
3453
func RequestUnparsedResponse(url string, header http.Header) (resp *http.Response, err error) {
3554
req, err := http.NewRequest("GET", url, nil)
3655
if err != nil {

providers/facebook.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package providers
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"net/http"
7+
"net/url"
8+
9+
"github.com/bitly/oauth2_proxy/api"
10+
)
11+
12+
type FacebookProvider struct {
13+
*ProviderData
14+
}
15+
16+
func NewFacebookProvider(p *ProviderData) *FacebookProvider {
17+
p.ProviderName = "Facebook"
18+
if p.LoginURL.String() == "" {
19+
p.LoginURL = &url.URL{Scheme: "https",
20+
Host: "www.facebook.com",
21+
Path: "/v2.5/dialog/oauth",
22+
// ?granted_scopes=true
23+
}
24+
}
25+
if p.RedeemURL.String() == "" {
26+
p.RedeemURL = &url.URL{Scheme: "https",
27+
Host: "graph.facebook.com",
28+
Path: "/v2.5/oauth/access_token",
29+
}
30+
}
31+
if p.ProfileURL.String() == "" {
32+
p.ProfileURL = &url.URL{Scheme: "https",
33+
Host: "graph.facebook.com",
34+
Path: "/v2.5/me",
35+
}
36+
}
37+
if p.ValidateURL.String() == "" {
38+
p.ValidateURL = p.ProfileURL
39+
}
40+
if p.Scope == "" {
41+
p.Scope = "public_profile email"
42+
}
43+
return &FacebookProvider{ProviderData: p}
44+
}
45+
46+
func getFacebookHeader(access_token string) http.Header {
47+
header := make(http.Header)
48+
header.Set("Accept", "application/json")
49+
header.Set("x-li-format", "json")
50+
header.Set("Authorization", fmt.Sprintf("Bearer %s", access_token))
51+
return header
52+
}
53+
54+
func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) {
55+
if s.AccessToken == "" {
56+
return "", errors.New("missing access token")
57+
}
58+
req, err := http.NewRequest("GET", p.ProfileURL.String()+"?fields=name,email", nil)
59+
if err != nil {
60+
return "", err
61+
}
62+
req.Header = getFacebookHeader(s.AccessToken)
63+
64+
type result struct {
65+
Email string
66+
}
67+
var r result
68+
err = api.RequestJson(req, &r)
69+
if err != nil {
70+
return "", err
71+
}
72+
if r.Email == "" {
73+
return "", errors.New("no email")
74+
}
75+
return r.Email, nil
76+
}
77+
78+
func (p *FacebookProvider) ValidateSessionState(s *SessionState) bool {
79+
return validateToken(p, s.AccessToken, getFacebookHeader(s.AccessToken))
80+
}

providers/providers.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ func New(provider string, p *ProviderData) Provider {
2222
return NewMyUsaProvider(p)
2323
case "linkedin":
2424
return NewLinkedInProvider(p)
25+
case "facebook":
26+
return NewFacebookProvider(p)
2527
case "github":
2628
return NewGitHubProvider(p)
2729
case "azure":

0 commit comments

Comments
 (0)