Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dex
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
dex
Commits
fd5e508f
Commit
fd5e508f
authored
Aug 08, 2016
by
Eric Chiang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
*: implement the OpenID Connect connector
parent
95a61454
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
150 additions
and
9 deletions
+150
-9
config.go
cmd/poke/config.go
+11
-9
oidc.go
connector/oidc/oidc.go
+131
-0
config-dev.yaml
example/config-dev.yaml
+8
-0
No files found.
cmd/poke/config.go
View file @
fd5e508f
...
...
@@ -7,6 +7,7 @@ import (
"github.com/coreos/poke/connector/github"
"github.com/coreos/poke/connector/ldap"
"github.com/coreos/poke/connector/mock"
"github.com/coreos/poke/connector/oidc"
"github.com/coreos/poke/storage"
"github.com/coreos/poke/storage/kubernetes"
"github.com/coreos/poke/storage/memory"
...
...
@@ -100,33 +101,34 @@ func (c *Connector) UnmarshalYAML(unmarshal func(interface{}) error) error {
c
.
Name
=
connectorMetadata
.
Name
c
.
ID
=
connectorMetadata
.
ID
var
err
error
switch
c
.
Type
{
case
"mock"
:
var
config
struct
{
Config
mock
.
Config
`yaml:"config"`
}
if
err
:=
unmarshal
(
&
config
);
err
!=
nil
{
return
err
}
err
=
unmarshal
(
&
config
)
c
.
Config
=
&
config
.
Config
case
"ldap"
:
var
config
struct
{
Config
ldap
.
Config
`yaml:"config"`
}
if
err
:=
unmarshal
(
&
config
);
err
!=
nil
{
return
err
}
err
=
unmarshal
(
&
config
)
c
.
Config
=
&
config
.
Config
case
"github"
:
var
config
struct
{
Config
github
.
Config
`yaml:"config"`
}
if
err
:=
unmarshal
(
&
config
);
err
!=
nil
{
return
err
err
=
unmarshal
(
&
config
)
c
.
Config
=
&
config
.
Config
case
"oidc"
:
var
config
struct
{
Config
oidc
.
Config
`yaml:"config"`
}
err
=
unmarshal
(
&
config
)
c
.
Config
=
&
config
.
Config
default
:
return
fmt
.
Errorf
(
"unknown connector type %q"
,
c
.
Type
)
}
return
nil
return
err
}
connector/oidc/oidc.go
View file @
fd5e508f
// Package oidc implements logging in through OpenID Connect providers.
package
oidc
import
(
"errors"
"fmt"
"net/http"
"os"
"github.com/ericchiang/oidc"
"golang.org/x/net/context"
"golang.org/x/oauth2"
"github.com/coreos/poke/connector"
)
// Config holds configuration options for OpenID Connect logins.
type
Config
struct
{
Issuer
string
`yaml:"issuer"`
ClientID
string
`yaml:"clientID"`
ClientSecret
string
`yaml:"clientSecret"`
RedirectURI
string
`yaml:"redirectURI"`
Scopes
[]
string
`yaml:"scopes"`
// defaults to "profile" and "email"
}
// Open returns a connector which can be used to login users through an upstream
// OpenID Connect provider.
func
(
c
*
Config
)
Open
()
(
conn
connector
.
Connector
,
err
error
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
provider
,
err
:=
oidc
.
NewProvider
(
ctx
,
c
.
Issuer
)
if
err
!=
nil
{
cancel
()
return
nil
,
fmt
.
Errorf
(
"failed to get provider: %v"
,
err
)
}
scopes
:=
[]
string
{
oidc
.
ScopeOpenID
}
if
len
(
c
.
Scopes
)
>
0
{
scopes
=
append
(
scopes
,
c
.
Scopes
...
)
}
else
{
scopes
=
append
(
scopes
,
"profile"
,
"email"
)
}
clientID
:=
os
.
ExpandEnv
(
c
.
ClientID
)
return
&
oidcConnector
{
redirectURI
:
c
.
RedirectURI
,
oauth2Config
:
&
oauth2
.
Config
{
ClientID
:
clientID
,
ClientSecret
:
os
.
ExpandEnv
(
c
.
ClientSecret
),
Endpoint
:
provider
.
Endpoint
(),
Scopes
:
scopes
,
RedirectURL
:
c
.
RedirectURI
,
},
verifier
:
provider
.
NewVerifier
(
ctx
,
oidc
.
VerifyExpiry
(),
oidc
.
VerifyAudience
(
clientID
),
),
},
nil
}
var
(
_
connector
.
CallbackConnector
=
(
*
oidcConnector
)(
nil
)
)
type
oidcConnector
struct
{
redirectURI
string
oauth2Config
*
oauth2
.
Config
verifier
*
oidc
.
IDTokenVerifier
ctx
context
.
Context
cancel
context
.
CancelFunc
}
func
(
c
*
oidcConnector
)
Close
()
error
{
c
.
cancel
()
return
nil
}
func
(
c
*
oidcConnector
)
LoginURL
(
callbackURL
,
state
string
)
(
string
,
error
)
{
if
c
.
redirectURI
!=
callbackURL
{
return
""
,
fmt
.
Errorf
(
"expected callback URL did not match the URL in the config"
)
}
return
c
.
oauth2Config
.
AuthCodeURL
(
state
),
nil
}
type
oauth2Error
struct
{
error
string
errorDescription
string
}
func
(
e
*
oauth2Error
)
Error
()
string
{
if
e
.
errorDescription
==
""
{
return
e
.
error
}
return
e
.
error
+
": "
+
e
.
errorDescription
}
func
(
c
*
oidcConnector
)
HandleCallback
(
r
*
http
.
Request
)
(
identity
connector
.
Identity
,
state
string
,
err
error
)
{
q
:=
r
.
URL
.
Query
()
if
errType
:=
q
.
Get
(
"error"
);
errType
!=
""
{
return
identity
,
""
,
&
oauth2Error
{
errType
,
q
.
Get
(
"error_description"
)}
}
token
,
err
:=
c
.
oauth2Config
.
Exchange
(
c
.
ctx
,
q
.
Get
(
"code"
))
if
err
!=
nil
{
return
identity
,
""
,
fmt
.
Errorf
(
"oidc: failed to get token: %v"
,
err
)
}
rawIDToken
,
ok
:=
token
.
Extra
(
"id_token"
)
.
(
string
)
if
!
ok
{
return
identity
,
""
,
errors
.
New
(
"oidc: no id_token in token response"
)
}
idToken
,
err
:=
c
.
verifier
.
Verify
(
rawIDToken
)
if
err
!=
nil
{
return
identity
,
""
,
fmt
.
Errorf
(
"oidc: failed to verify ID Token: %v"
,
err
)
}
var
claims
struct
{
Username
string
`json:"name"`
Email
string
`json:"email"`
EmailVerified
bool
`json:"email_verified"`
}
if
err
:=
idToken
.
Claims
(
&
claims
);
err
!=
nil
{
return
identity
,
""
,
fmt
.
Errorf
(
"oidc: failed to decode claims: %v"
,
err
)
}
identity
=
connector
.
Identity
{
UserID
:
idToken
.
Subject
,
Username
:
claims
.
Username
,
Email
:
claims
.
Email
,
EmailVerified
:
claims
.
EmailVerified
,
}
return
identity
,
q
.
Get
(
"state"
),
nil
}
example/config-dev.yaml
View file @
fd5e508f
...
...
@@ -18,6 +18,14 @@ connectors:
clientSecret
:
"
$GITHUB_CLIENT_SECRET"
redirectURI
:
http://127.0.0.1:5556/callback/github
org
:
kubernetes
-
type
:
oidc
id
:
google
name
:
Google Account
config
:
issuer
:
https://accounts.google.com
clientID
:
"
$GOOGLE_OAUTH2_CLIENT_ID"
clientSecret
:
"
$GOOGLE_OAUTH2_CLIENT_SECRET"
redirectURI
:
http://127.0.0.1:5556/callback/google
staticClients
:
-
id
:
example-app
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment