Skip to content

Commit

Permalink
Passport provider added
Browse files Browse the repository at this point in the history
  • Loading branch information
Kirill Melnikov committed May 12, 2017
1 parent 120a47a commit 2c9d46f
Show file tree
Hide file tree
Showing 22 changed files with 236 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea/
google_auth_proxy
oauth2_proxy
# Go.gitignore
Expand Down Expand Up @@ -28,3 +29,7 @@ dist

# Editor swap/temp files
.*.swp
etc/
test
oauth2_proxy
/vendor/*/
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM golang:onbuild-alpine
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.PHONY: build

clean:
rm ./oauth2_proxy
docker-compose down

default: build

build:
@go build -a .

run: clean build
./oauth2_proxy -provider=passport -config etc/oauth2_proxy.cfg

docker:
docker-compose build

up: docker
docker-compose up -d
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ oauth2_proxy
A reverse proxy and static file server that provides authentication using Providers (Google, GitHub, and others)
to validate accounts by email, domain or group.

[![Build Status](https://secure.travis-ci.org/bitly/oauth2_proxy.png?branch=master)](http://travis-ci.org/bitly/oauth2_proxy)
[![Build Status](https://secure.travis-ci.org/melnikk/oauth2_proxy.png?branch=master)](http://travis-ci.org/melnikk/oauth2_proxy)


![Sign In Page](https://cloud.githubusercontent.com/assets/45028/4970624/7feb7dd8-6886-11e4-93e0-c9904af44ea8.png)
Expand All @@ -17,7 +17,7 @@ to validate accounts by email, domain or group.

## Installation

1. Download [Prebuilt Binary](https://github.com/bitly/oauth2_proxy/releases) (current release is `v2.1`) or build with `$ go get github.com/bitly/oauth2_proxy` which will put the binary in `$GOROOT/bin`
1. Download [Prebuilt Binary](https://github.com/melnikk/oauth2_proxy/releases) (current release is `v2.1`) or build with `$ go get github.com/melnikk/oauth2_proxy` which will put the binary in `$GOROOT/bin`
2. Select a Provider and Register an OAuth Application with a Provider
3. Configure OAuth2 Proxy using config file, command line options, or environment variables
4. Configure SSL or Deploy behind a SSL endpoint (example provided for Nginx)
Expand Down
2 changes: 1 addition & 1 deletion contrib/oauth2_proxy.cfg.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## OAuth2 Proxy Config File
## https://github.com/bitly/oauth2_proxy
## https://github.com/melnikk/oauth2_proxy

## <addr>:<port> to listen on for HTTP/HTTPS clients
# http_address = "127.0.0.1:4180"
Expand Down
30 changes: 30 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: '2'

services:

nginx:
image: nginx
networks:
oauth:
ipv4_address: 172.15.66.10

proxy:
build: .
image: melnikk/oauth2_proxy
volumes:
- "./etc/oauth2_proxy.cfg:/etc/oauth2_proxy.cfg"
command: /etc/oauth2_proxy.cfg
networks:
oauth:
ipv4_address: 172.15.66.50

networks:
oauth:
driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "false"
ipam:
driver: default
config:
- subnet: 172.15.66.0/24
gateway: 172.15.66.1
4 changes: 2 additions & 2 deletions oauthproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
"time"

"github.com/18F/hmacauth"
"github.com/bitly/oauth2_proxy/cookie"
"github.com/bitly/oauth2_proxy/providers"
"github.com/melnikk/oauth2_proxy/cookie"
"github.com/melnikk/oauth2_proxy/providers"
)

const SignatureHeader = "GAP-Signature"
Expand Down
7 changes: 4 additions & 3 deletions oauthproxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ package main
import (
"crypto"
"encoding/base64"
"github.com/18F/hmacauth"
"github.com/bitly/oauth2_proxy/providers"
"github.com/bmizerany/assert"
"io"
"io/ioutil"
"log"
Expand All @@ -17,6 +14,10 @@ import (
"strings"
"testing"
"time"

"github.com/18F/hmacauth"
"github.com/bmizerany/assert"
"github.com/melnikk/oauth2_proxy/providers"
)

func init() {
Expand Down
9 changes: 8 additions & 1 deletion options.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"time"

"github.com/18F/hmacauth"
"github.com/bitly/oauth2_proxy/providers"
"github.com/melnikk/oauth2_proxy/providers"
)

// Configuration Options that can be set by Command Line Flag, or Config File
Expand Down Expand Up @@ -49,6 +49,7 @@ type Options struct {
CookieHttpOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"`

Upstreams []string `flag:"upstream" cfg:"upstreams"`
Allowed map[string]Customer `cfg:"allowed"`
SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"`
PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password"`
Expand Down Expand Up @@ -83,6 +84,11 @@ type Options struct {
signatureData *SignatureData
}

type Customer struct {
Hostname string
Groups []string
}

type SignatureData struct {
hash crypto.Hash
key string
Expand All @@ -107,6 +113,7 @@ func NewOptions() *Options {
PassHostHeader: true,
ApprovalPrompt: "force",
RequestLogging: true,
Allowed: make(map[string]Customer),
}
}

Expand Down
2 changes: 1 addition & 1 deletion providers/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"errors"
"fmt"
"github.com/bitly/go-simplejson"
"github.com/bitly/oauth2_proxy/api"
"github.com/melnikk/oauth2_proxy/api"
"log"
"net/http"
"net/url"
Expand Down
2 changes: 1 addition & 1 deletion providers/facebook.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"net/http"
"net/url"

"github.com/bitly/oauth2_proxy/api"
"github.com/melnikk/oauth2_proxy/api"
)

type FacebookProvider struct {
Expand Down
2 changes: 1 addition & 1 deletion providers/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"net/http"
"net/url"

"github.com/bitly/oauth2_proxy/api"
"github.com/melnikk/oauth2_proxy/api"
)

type GitLabProvider struct {
Expand Down
2 changes: 1 addition & 1 deletion providers/internal_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"net/http"
"net/url"

"github.com/bitly/oauth2_proxy/api"
"github.com/melnikk/oauth2_proxy/api"
)

// stripToken is a helper function to obfuscate "access_token"
Expand Down
2 changes: 1 addition & 1 deletion providers/linkedin.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"net/http"
"net/url"

"github.com/bitly/oauth2_proxy/api"
"github.com/melnikk/oauth2_proxy/api"
)

type LinkedInProvider struct {
Expand Down
2 changes: 1 addition & 1 deletion providers/myusa.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"net/http"
"net/url"

"github.com/bitly/oauth2_proxy/api"
"github.com/melnikk/oauth2_proxy/api"
)

type MyUsaProvider struct {
Expand Down
121 changes: 121 additions & 0 deletions providers/passport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package providers

import (
"fmt"
"encoding/json"
"encoding/base64"
"net/url"
"bytes"
"io/ioutil"
"errors"
"net/http"
"github.com/dgrijalva/jwt-go"
"log"
"strings"
)

// PassportProvider of auth
type PassportProvider struct {
*ProviderData
}

// NewPassportProvider creates passport provider
func NewPassportProvider(p *ProviderData) *PassportProvider {
p.ProviderName = "Passport"

return &PassportProvider{ProviderData: p}
}


func (p *PassportProvider) Redeem(redirectURL, code string) (s *SessionState, err error) {
if code == "" {
err = errors.New("missing code")
return
}

params := url.Values{}
params.Add("redirect_uri", redirectURL)
params.Add("client_id", p.ClientID)
params.Add("client_secret", p.ClientSecret)
params.Add("code", code)
params.Add("grant_type", "authorization_code")
if p.ProtectedResource != nil && p.ProtectedResource.String() != "" {
params.Add("resource", p.ProtectedResource.String())
}

var req *http.Request
req, err = http.NewRequest("POST", p.RedeemURL.String(), bytes.NewBufferString(params.Encode()))
if err != nil {
return
}

req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

token := []byte(fmt.Sprintf("%s:%s", p.ClientID, p.ClientSecret))
req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString(token)))

var resp *http.Response
resp, err = http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
var body []byte
body, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return
}

if resp.StatusCode != 200 {
err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemURL.String(), body)
return
}

// blindly try json and x-www-form-urlencoded
var jsonResponse struct {
AccessToken string `json:"access_token"`
}
err = json.Unmarshal(body, &jsonResponse)

if err == nil {

if err != nil {
return
}
s = &SessionState{
AccessToken: jsonResponse.AccessToken,
}
return
}

var v url.Values
v, err = url.ParseQuery(string(body))
if err != nil {
return
}
if a := v.Get("access_token"); a != "" {
s = &SessionState{AccessToken: a}
} else {
err = fmt.Errorf("no access token found %s", body)
}
return
}

func (p *PassportProvider) GetEmailAddress(s *SessionState) (string, error) {
email := ""
token, err := jwt.Parse(s.AccessToken, func(token *jwt.Token) (interface{}, error) {
publicKey, err := ioutil.ReadFile("etc/passport.pub")
if err != nil {
log.Printf("Error loading public key: %s", err.Error())
}
return publicKey, nil
})
if err==nil && token.Valid {
login := strings.ToLower(token.Claims["sub"].(string))

loginParts := strings.Split(login,"\\")
email = fmt.Sprintf("%s@%s", loginParts[1], loginParts[0])
}
return email, err
}
2 changes: 1 addition & 1 deletion providers/provider_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"net/http"
"net/url"

"github.com/bitly/oauth2_proxy/cookie"
"github.com/melnikk/oauth2_proxy/cookie"
)

func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err error) {
Expand Down
4 changes: 3 additions & 1 deletion providers/providers.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package providers

import (
"github.com/bitly/oauth2_proxy/cookie"
"github.com/melnikk/oauth2_proxy/cookie"
)

type Provider interface {
Expand All @@ -18,6 +18,8 @@ type Provider interface {

func New(provider string, p *ProviderData) Provider {
switch provider {
case "passport":
return NewPassportProvider(p)
case "myusa":
return NewMyUsaProvider(p)
case "linkedin":
Expand Down
2 changes: 1 addition & 1 deletion providers/session_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"strings"
"time"

"github.com/bitly/oauth2_proxy/cookie"
"github.com/melnikk/oauth2_proxy/cookie"
)

type SessionState struct {
Expand Down
2 changes: 1 addition & 1 deletion providers/session_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"
"time"

"github.com/bitly/oauth2_proxy/cookie"
"github.com/melnikk/oauth2_proxy/cookie"
"github.com/bmizerany/assert"
)

Expand Down
2 changes: 1 addition & 1 deletion templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func getTemplates() *template.Template {
<footer>
{{ if eq .Footer "-" }}
{{ else if eq .Footer ""}}
Secured with <a href="https://github.com/bitly/oauth2_proxy#oauth2_proxy">OAuth2 Proxy</a> version {{.Version}}
Secured with <a href="https://github.com/melnikk/oauth2_proxy#oauth2_proxy">OAuth2 Proxy</a> version {{.Version}}
{{ else }}
{{.Footer}}
{{ end }}
Expand Down
Loading

0 comments on commit 2c9d46f

Please sign in to comment.