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

providers: add okta (take two) #528

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Valid providers are :
* [GitHub](#github-auth-provider)
* [GitLab](#gitlab-auth-provider)
* [LinkedIn](#linkedin-auth-provider)
* [Okta](#okta-auth-provider)

The provider can be selected using the `provider` configuration value.

Expand Down Expand Up @@ -155,6 +156,10 @@ OpenID Connect is a spec for OAUTH 2.0 + identity that is implemented by many ma
-cookie-secure=false
-email-domain example.com

### Okta Auth Provider

[Okta](https://www.okta.com/) is a hosted SSO provider. You will need to set the `okta-domain` to your organization's Okta domain.

## Email Authentication

To authorize by email domain use `--email-domain=yourcompany.com`. To authorize individual email addresses use `--authenticated-emails-file=/path/to/file` with one email per line. To authorize all email addresses use `--email-domain=*`.
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func main() {
flagSet.Var(&googleGroups, "google-group", "restrict logins to members of this google group (may be given multiple times).")
flagSet.String("google-admin-email", "", "the google admin to impersonate for api calls")
flagSet.String("google-service-account-json", "", "the path to the service account json credentials")
flagSet.String("okta-domain", "", "the full domain for which your organization's okta is configured (example.okta.com)")
flagSet.String("client-id", "", "the OAuth Client ID: ie: \"123456.apps.googleusercontent.com\"")
flagSet.String("client-secret", "", "the OAuth Client Secret")
flagSet.String("authenticated-emails-file", "", "authenticate against emails via file (one per line)")
Expand Down
3 changes: 3 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type Options struct {
GoogleGroups []string `flag:"google-group" cfg:"google_group"`
GoogleAdminEmail string `flag:"google-admin-email" cfg:"google_admin_email"`
GoogleServiceAccountJSON string `flag:"google-service-account-json" cfg:"google_service_account_json"`
OktaDomain string `flag:"okta-domain" cfg:"okta_domain"`
HtpasswdFile string `flag:"htpasswd-file" cfg:"htpasswd_file"`
DisplayHtpasswdForm bool `flag:"display-htpasswd-form" cfg:"display_htpasswd_form"`
CustomTemplatesDir string `flag:"custom-templates-dir" cfg:"custom_templates_dir"`
Expand Down Expand Up @@ -278,6 +279,8 @@ func parseProviderInfo(o *Options, msgs []string) []string {
} else {
p.Verifier = o.oidcVerifier
}
case *providers.OktaProvider:
p.SetOktaDomain(o.OktaDomain)
}
return msgs
}
Expand Down
88 changes: 88 additions & 0 deletions providers/okta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package providers

import (
"fmt"
"log"
"net/http"
"net/url"

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

type OktaProvider struct {
*ProviderData
}

func NewOktaProvider(p *ProviderData) *OktaProvider {
p.ProviderName = "Okta"
if p.Scope == "" {
p.Scope = "openid profile email"
}
return &OktaProvider{ProviderData: p}
}

func (p *OktaProvider) SetOktaDomain(domain string) {
if p.LoginURL == nil || p.LoginURL.String() == "" {
p.LoginURL = &url.URL{
Scheme: "https",
Host: domain,
Path: "/oauth2/v1/authorize",
}
}
if p.RedeemURL == nil || p.RedeemURL.String() == "" {
p.RedeemURL = &url.URL{
Scheme: "https",
Host: domain,
Path: "/oauth2/v1/token",
}
}
if p.ValidateURL == nil || p.ValidateURL.String() == "" {
p.ValidateURL = &url.URL{
Scheme: "https",
Host: domain,
Path: "/oauth2/v1/userinfo",
}
}
}

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

func (p *OktaProvider) GetEmailAddress(s *SessionState) (string, error) {
req, err := http.NewRequest("GET",
p.ValidateURL.String(), nil)
if err != nil {
log.Printf("failed building request %s", err)
return "", err
}
req.Header = getOktaHeader(s.AccessToken)
json, err := api.Request(req)
if err != nil {
log.Printf("failed making request %s", err)
return "", err
}
return json.Get("email").String()
}

func (p *OktaProvider) GetUserName(s *SessionState) (string, error) {
req, err := http.NewRequest("GET",
p.ValidateURL.String(), nil)
if err != nil {
log.Printf("failed building request %s", err)
return "", err
}
req.Header = getOktaHeader(s.AccessToken)
json, err := api.Request(req)
if err != nil {
log.Printf("failed making request %s", err)
return "", err
}
return json.Get("preferred_username").String()
}

func (p *OktaProvider) ValidateSessionState(s *SessionState) bool {
return validateToken(p, s.AccessToken, getOktaHeader(s.AccessToken))
}
2 changes: 2 additions & 0 deletions providers/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ func New(provider string, p *ProviderData) Provider {
return NewGitLabProvider(p)
case "oidc":
return NewOIDCProvider(p)
case "okta":
return NewOktaProvider(p)
default:
return NewGoogleProvider(p)
}
Expand Down