Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
dex
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
hdacloud
dex
Commits
1211a86d
Commit
1211a86d
authored
4 years ago
by
m.nabokikh
Browse files
Options
Downloads
Patches
Plain Diff
fix: use /token endpoint to get tokens with device flow
Signed-off-by:
m.nabokikh
<
maksim.nabokikh@flant.com
>
parent
3c5a631c
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
server/deviceflowhandlers.go
+56
-52
56 additions, 52 deletions
server/deviceflowhandlers.go
server/handlers.go
+23
-4
23 additions, 4 deletions
server/handlers.go
server/server.go
+2
-1
2 additions, 1 deletion
server/server.go
server/server_test.go
+1
-1
1 addition, 1 deletion
server/server_test.go
with
82 additions
and
58 deletions
server/deviceflowhandlers.go
+
56
−
52
View file @
1211a86d
...
@@ -151,7 +151,7 @@ func (s *Server) handleDeviceCode(w http.ResponseWriter, r *http.Request) {
...
@@ -151,7 +151,7 @@ func (s *Server) handleDeviceCode(w http.ResponseWriter, r *http.Request) {
}
}
}
}
func
(
s
*
Server
)
handleDeviceToken
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
(
s
*
Server
)
handleDeviceToken
Grant
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
switch
r
.
Method
{
switch
r
.
Method
{
case
http
.
MethodPost
:
case
http
.
MethodPost
:
...
@@ -162,68 +162,72 @@ func (s *Server) handleDeviceToken(w http.ResponseWriter, r *http.Request) {
...
@@ -162,68 +162,72 @@ func (s *Server) handleDeviceToken(w http.ResponseWriter, r *http.Request) {
return
return
}
}
deviceCode
:=
r
.
Form
.
Get
(
"device_code"
)
if
deviceCode
==
""
{
s
.
tokenErrHelper
(
w
,
errInvalidRequest
,
"No device code received"
,
http
.
StatusBadRequest
)
return
}
grantType
:=
r
.
PostFormValue
(
"grant_type"
)
grantType
:=
r
.
PostFormValue
(
"grant_type"
)
if
grantType
!=
grantTypeDeviceCode
{
if
grantType
!=
grantTypeDeviceCode
{
s
.
tokenErrHelper
(
w
,
errInvalidGrant
,
""
,
http
.
StatusBadRequest
)
s
.
tokenErrHelper
(
w
,
errInvalidGrant
,
""
,
http
.
StatusBadRequest
)
return
return
}
}
now
:=
s
.
now
()
s
.
handleDeviceToken
(
w
,
r
)
default
:
s
.
renderError
(
r
,
w
,
http
.
StatusBadRequest
,
"Requested resource does not exist."
)
}
}
// Grab the device token, check validity
func
(
s
*
Server
)
handleDeviceToken
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
deviceToken
,
err
:=
s
.
storage
.
GetDeviceToken
(
deviceCode
)
deviceCode
:=
r
.
Form
.
Get
(
"device_code"
)
if
err
!=
nil
{
if
deviceCode
==
""
{
if
err
!=
storage
.
ErrNotFound
{
s
.
tokenErrHelper
(
w
,
errInvalidRequest
,
"No device code received"
,
http
.
StatusBadRequest
)
s
.
logger
.
Errorf
(
"failed to get device code: %v"
,
err
)
return
}
}
s
.
tokenErrHelper
(
w
,
errInvalidRequest
,
"Invalid Device code."
,
http
.
StatusBadRequest
)
return
}
else
if
now
.
After
(
deviceToken
.
Expiry
)
{
s
.
tokenErrHelper
(
w
,
deviceTokenExpired
,
""
,
http
.
StatusBadRequest
)
return
}
// Rate Limiting check
now
:=
s
.
now
()
slowDown
:=
false
pollInterval
:=
deviceToken
.
PollIntervalSeconds
// Grab the device token, check validity
minRequestTime
:=
deviceToken
.
LastRequestTime
.
Add
(
time
.
Second
*
time
.
Duration
(
pollInterval
))
deviceToken
,
err
:=
s
.
storage
.
GetDeviceToken
(
deviceCode
)
if
now
.
Before
(
minRequestTime
)
{
if
err
!=
nil
{
slowDown
=
true
if
err
!=
storage
.
ErrNotFound
{
// Continually increase the poll interval until the user waits the proper time
s
.
logger
.
Errorf
(
"failed to get device code: %v"
,
err
)
pollInterval
+=
5
}
else
{
pollInterval
=
5
}
}
s
.
tokenErrHelper
(
w
,
errInvalidRequest
,
"Invalid Device code."
,
http
.
StatusBadRequest
)
return
}
else
if
now
.
After
(
deviceToken
.
Expiry
)
{
s
.
tokenErrHelper
(
w
,
deviceTokenExpired
,
""
,
http
.
StatusBadRequest
)
return
}
switch
deviceToken
.
Status
{
// Rate Limiting check
case
deviceTokenPending
:
slowDown
:=
false
updater
:=
func
(
old
storage
.
DeviceToken
)
(
storage
.
DeviceToken
,
error
)
{
pollInterval
:=
deviceToken
.
PollIntervalSeconds
old
.
PollIntervalSeconds
=
pollInterval
minRequestTime
:=
deviceToken
.
LastRequestTime
.
Add
(
time
.
Second
*
time
.
Duration
(
pollInterval
))
old
.
LastRequestTime
=
now
if
now
.
Before
(
minRequestTime
)
{
return
old
,
nil
slowDown
=
true
}
// Continually increase the poll interval until the user waits the proper time
// Update device token last request time in storage
pollInterval
+=
5
if
err
:=
s
.
storage
.
UpdateDeviceToken
(
deviceCode
,
updater
);
err
!=
nil
{
}
else
{
s
.
logger
.
Errorf
(
"failed to update device token: %v"
,
err
)
pollInterval
=
5
s
.
renderError
(
r
,
w
,
http
.
StatusInternalServerError
,
""
)
}
return
}
switch
deviceToken
.
Status
{
if
slowDown
{
case
deviceTokenPending
:
s
.
tokenErrHelper
(
w
,
deviceTokenSlowDown
,
""
,
http
.
StatusBadRequest
)
updater
:=
func
(
old
storage
.
DeviceToken
)
(
storage
.
DeviceToken
,
error
)
{
}
else
{
old
.
PollIntervalSeconds
=
pollInterval
s
.
tokenErrHelper
(
w
,
deviceTokenPending
,
""
,
http
.
StatusUnauthorized
)
old
.
LastRequestTime
=
now
}
return
old
,
nil
case
deviceTokenComplete
:
w
.
Write
([]
byte
(
deviceToken
.
Token
))
}
}
default
:
// Update device token last request time in storage
s
.
renderError
(
r
,
w
,
http
.
StatusBadRequest
,
"Requested resource does not exist."
)
if
err
:=
s
.
storage
.
UpdateDeviceToken
(
deviceCode
,
updater
);
err
!=
nil
{
s
.
logger
.
Errorf
(
"failed to update device token: %v"
,
err
)
s
.
renderError
(
r
,
w
,
http
.
StatusInternalServerError
,
""
)
return
}
if
slowDown
{
s
.
tokenErrHelper
(
w
,
deviceTokenSlowDown
,
""
,
http
.
StatusBadRequest
)
}
else
{
s
.
tokenErrHelper
(
w
,
deviceTokenPending
,
""
,
http
.
StatusUnauthorized
)
}
case
deviceTokenComplete
:
w
.
Write
([]
byte
(
deviceToken
.
Token
))
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
server/handlers.go
+
23
−
4
View file @
1211a86d
...
@@ -652,7 +652,7 @@ func (s *Server) sendCodeResponse(w http.ResponseWriter, r *http.Request, authRe
...
@@ -652,7 +652,7 @@ func (s *Server) sendCodeResponse(w http.ResponseWriter, r *http.Request, authRe
http
.
Redirect
(
w
,
r
,
u
.
String
(),
http
.
StatusSeeOther
)
http
.
Redirect
(
w
,
r
,
u
.
String
(),
http
.
StatusSeeOther
)
}
}
func
(
s
*
Server
)
handleToken
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
(
s
*
Server
)
withClientFromStorage
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
handler
func
(
http
.
ResponseWriter
,
*
http
.
Request
,
storage
.
Client
)
)
{
clientID
,
clientSecret
,
ok
:=
r
.
BasicAuth
()
clientID
,
clientSecret
,
ok
:=
r
.
BasicAuth
()
if
ok
{
if
ok
{
var
err
error
var
err
error
...
@@ -689,14 +689,33 @@ func (s *Server) handleToken(w http.ResponseWriter, r *http.Request) {
...
@@ -689,14 +689,33 @@ func (s *Server) handleToken(w http.ResponseWriter, r *http.Request) {
return
return
}
}
handler
(
w
,
r
,
client
)
}
func
(
s
*
Server
)
handleToken
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
if
r
.
Method
!=
http
.
MethodPost
{
s
.
tokenErrHelper
(
w
,
errInvalidRequest
,
"method not allowed"
,
http
.
StatusBadRequest
)
return
}
err
:=
r
.
ParseForm
()
if
err
!=
nil
{
s
.
logger
.
Errorf
(
"Could not parse request body: %v"
,
err
)
s
.
tokenErrHelper
(
w
,
errInvalidRequest
,
""
,
http
.
StatusBadRequest
)
return
}
grantType
:=
r
.
PostFormValue
(
"grant_type"
)
grantType
:=
r
.
PostFormValue
(
"grant_type"
)
switch
grantType
{
switch
grantType
{
case
grantTypeDeviceCode
:
s
.
handleDeviceToken
(
w
,
r
)
case
grantTypeAuthorizationCode
:
case
grantTypeAuthorizationCode
:
s
.
handleAuthCode
(
w
,
r
,
client
)
s
.
withClientFromStorage
(
w
,
r
,
s
.
handleAuthCode
)
case
grantTypeRefreshToken
:
case
grantTypeRefreshToken
:
s
.
handleRefreshToken
(
w
,
r
,
client
)
s
.
withClientFromStorage
(
w
,
r
,
s
.
handleRefreshToken
)
case
grantTypePassword
:
case
grantTypePassword
:
s
.
handlePasswordGrant
(
w
,
r
,
client
)
s
.
withClientFromStorage
(
w
,
r
,
s
.
handlePasswordGrant
)
default
:
default
:
s
.
tokenErrHelper
(
w
,
errInvalidGrant
,
""
,
http
.
StatusBadRequest
)
s
.
tokenErrHelper
(
w
,
errInvalidGrant
,
""
,
http
.
StatusBadRequest
)
}
}
...
...
This diff is collapsed.
Click to expand it.
server/server.go
+
2
−
1
View file @
1211a86d
...
@@ -320,7 +320,8 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy)
...
@@ -320,7 +320,8 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy)
handleFunc
(
"/device"
,
s
.
handleDeviceExchange
)
handleFunc
(
"/device"
,
s
.
handleDeviceExchange
)
handleFunc
(
"/device/auth/verify_code"
,
s
.
verifyUserCode
)
handleFunc
(
"/device/auth/verify_code"
,
s
.
verifyUserCode
)
handleFunc
(
"/device/code"
,
s
.
handleDeviceCode
)
handleFunc
(
"/device/code"
,
s
.
handleDeviceCode
)
handleFunc
(
"/device/token"
,
s
.
handleDeviceToken
)
// TODO(nabokihms): deprecate and remove this endpoint, use /token instead
handleFunc
(
"/device/token"
,
s
.
handleDeviceTokenGrant
)
handleFunc
(
deviceCallbackURI
,
s
.
handleDeviceCallback
)
handleFunc
(
deviceCallbackURI
,
s
.
handleDeviceCallback
)
r
.
HandleFunc
(
path
.
Join
(
issuerURL
.
Path
,
"/callback"
),
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
r
.
HandleFunc
(
path
.
Join
(
issuerURL
.
Path
,
"/callback"
),
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
// Strip the X-Remote-* headers to prevent security issues on
// Strip the X-Remote-* headers to prevent security issues on
...
...
This diff is collapsed.
Click to expand it.
server/server_test.go
+
1
−
1
View file @
1211a86d
...
@@ -1583,7 +1583,7 @@ func TestOAuth2DeviceFlow(t *testing.T) {
...
@@ -1583,7 +1583,7 @@ func TestOAuth2DeviceFlow(t *testing.T) {
// Hit the Token Endpoint, and try and get an access token
// Hit the Token Endpoint, and try and get an access token
tokenURL
,
_
:=
url
.
Parse
(
issuer
.
String
())
tokenURL
,
_
:=
url
.
Parse
(
issuer
.
String
())
tokenURL
.
Path
=
path
.
Join
(
tokenURL
.
Path
,
"/
device/
token"
)
tokenURL
.
Path
=
path
.
Join
(
tokenURL
.
Path
,
"/token"
)
v
:=
url
.
Values
{}
v
:=
url
.
Values
{}
v
.
Add
(
"grant_type"
,
grantTypeDeviceCode
)
v
.
Add
(
"grant_type"
,
grantTypeDeviceCode
)
v
.
Add
(
"device_code"
,
deviceCode
.
DeviceCode
)
v
.
Add
(
"device_code"
,
deviceCode
.
DeviceCode
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment