Skip to content
This repository has been archived by the owner on Jan 24, 2019. It is now read-only.

Added OIDC support for UserInfo Endpoint Email Verification #481

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions providers/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package providers
import (
"context"
"fmt"
"net/http"
"time"

"golang.org/x/oauth2"

oidc "github.com/coreos/go-oidc"

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

type OIDCProvider struct {
Expand Down Expand Up @@ -57,10 +60,35 @@ func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err er
}

if claims.Email == "" {
return nil, fmt.Errorf("id_token did not contain an email")
if p.ProfileURL.String() == "" {
return nil, fmt.Errorf("id_token did not contain an email")
}

// If the userinfo endpoint profileURL is defined, then there
// is a chance the userinfo contents at the profileURL contain
// the email. Make a query to the userinfo endpoint, and
// attempt to locate the email from there.

req, err := http.NewRequest("GET", p.ProfileURL.String(), nil)
if err != nil {
return nil, err
}
req.Header = getOIDCHeader(token.AccessToken)

json, err := api.Request(req)
if err != nil {
return nil, err
}

email, err := json.Get("email").String()
if err != nil {
return nil, fmt.Errorf("id_token nor userinfo endpoint did not contain an email")
}

claims.Email = email
}
if claims.Verified != nil && !*claims.Verified {
return nil, fmt.Errorf("email in id_token (%s) isn't verified", claims.Email)
return nil, fmt.Errorf("id_token failed verification")
}

s = &SessionState{
Expand All @@ -83,3 +111,10 @@ func (p *OIDCProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) {
fmt.Printf("refreshed access token %s (expired on %s)\n", s, origExpiration)
return false, nil
}

func getOIDCHeader(access_token string) http.Header {
header := make(http.Header)
header.Set("Accept", "application/json")
header.Set("Authorization", fmt.Sprintf("Bearer %s", access_token))
return header
}