Skip to content

Commit 26a0e9a

Browse files
committed
The realization of the optimization of details
1 parent 2cb20c8 commit 26a0e9a

File tree

18 files changed

+372
-89
lines changed

18 files changed

+372
-89
lines changed

README.md

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,35 @@
11
OAuth 2.0
22
=========
3-
> [OAuth 2.0](http://oauth.net/2/) is the next evolution of the OAuth protocol which was originally created in late 2006.
3+
> An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.
44
55
[![GoDoc](https://godoc.org/gopkg.in/oauth2.v3?status.svg)](https://godoc.org/gopkg.in/oauth2.v3)
66
[![Go Report Card](https://goreportcard.com/badge/gopkg.in/oauth2.v3)](https://goreportcard.com/report/gopkg.in/oauth2.v3)
77
[![Build Status](https://travis-ci.org/go-oauth2/oauth2.svg?branch=master)](https://travis-ci.org/go-oauth2/oauth2)
88

9+
Protocol Flow
10+
-------------
11+
12+
```
13+
+--------+ +---------------+
14+
| |--(A)- Authorization Request ->| Resource |
15+
| | | Owner |
16+
| |<-(B)-- Authorization Grant ---| |
17+
| | +---------------+
18+
| |
19+
| | +---------------+
20+
| |--(C)-- Authorization Grant -->| Authorization |
21+
| Client | | Server |
22+
| |<-(D)----- Access Token -------| |
23+
| | +---------------+
24+
| |
25+
| | +---------------+
26+
| |--(E)----- Access Token ------>| Resource |
27+
| | | Server |
28+
| |<-(F)--- Protected Resource ---| |
29+
+--------+ +---------------+
30+
```
31+
32+
933
Quick Start
1034
-----------
1135

@@ -73,10 +97,12 @@ http://localhost:9096/authorize?response_type=code&client_id=1&redirect_uri=http
7397
Features
7498
--------
7599

76-
* Based on the [RFC 6749](https://tools.ietf.org/html/rfc6749) implementation
77100
* Easy to use
78-
* Modularity
79-
* Flexible
101+
* Based on the [RFC 6749](https://tools.ietf.org/html/rfc6749) implementation
102+
* Token storage support TTL
103+
* Support custom extension field
104+
* Support custom scope
105+
* Support custom expiration time of the access token
80106

81107
Example
82108
-------

example/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ Open the browser
2222

2323
[http://localhost:9094](http://localhost:9094)
2424

25+
![login](/server/testdata/login.png)
26+
![authorize](/server/testdata/authorize.png)
27+
2528
``` json
2629
{
2730
"access_token": "BIX-RYRPMHYY4L7O4QTP3Q",

example/server/static/auth.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
<div class="container">
1414
<div class="jumbotron">
1515
<form action="/auth" method="POST">
16-
<h1>The user authorization!</h1>
17-
<p>...</p>
18-
<p><button type="submit" class="btn btn-danger btn-lg">Authorize</button></p>
16+
<h1>Authorize</h1>
17+
<p>The client would like to perform actions on your behalf.</p>
18+
<p>
19+
<button type="submit" class="btn btn-primary btn-lg" style="width:200px;">Allow</button>
20+
</p>
1921
</form>
2022
</div>
2123
</div>

example/server/static/login.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<body>
1313
<div class="container">
14-
<h1>Login</h1>
14+
<h1>Login In</h1>
1515
<form action="/login" method="POST">
1616
<div class="form-group">
1717
<label for="username">User Name</label>
@@ -21,7 +21,7 @@ <h1>Login</h1>
2121
<label for="password">Password</label>
2222
<input type="password" class="form-control" name="password" placeholder="Please enter your password">
2323
</div>
24-
<button type="submit" class="btn btn-primary">Submit</button>
24+
<button type="submit" class="btn btn-success">Login</button>
2525
</form>
2626
</div>
2727
</body>
156 KB
Loading

example/server/testdata/login.png

153 KB
Loading

manage.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package oauth2
22

3+
import (
4+
"time"
5+
)
6+
37
// TokenGenerateRequest Provide to generate the token request parameters
48
type TokenGenerateRequest struct {
5-
ClientID string // The client information
6-
ClientSecret string // The client secret
7-
UserID string // The user id
8-
RedirectURI string // Redirect URI
9-
Scope string // Scope of authorization
10-
Code string // Authorization code
11-
Refresh string // Refreshing token
9+
ClientID string // The client information
10+
ClientSecret string // The client secret
11+
UserID string // The user id
12+
RedirectURI string // Redirect URI
13+
Scope string // Scope of authorization
14+
Code string // Authorization code
15+
Refresh string // Refreshing token
16+
AccessTokenExp time.Duration // Access token expiration time (in seconds)
1217
}
1318

1419
// Manager Authorization management interface

manage/manage_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func TestManager(t *testing.T) {
2121
So(cli.GetSecret(), ShouldEqual, "11")
2222
})
2323

24-
Convey("Memory store test", func() {
24+
Convey("Token test", func() {
2525
manager.MustTokenStorage(store.NewMemoryTokenStore())
2626
testManager(manager)
2727
})
@@ -37,8 +37,9 @@ func testManager(manager oauth2.Manager) {
3737
}
3838
cti, err := manager.GenerateAuthToken(oauth2.Code, reqParams)
3939
So(err, ShouldBeNil)
40+
Println(cti.GetCode())
4041

41-
code := cti.GetAccess()
42+
code := cti.GetCode()
4243
So(code, ShouldNotBeEmpty)
4344

4445
atParams := &oauth2.TokenGenerateRequest{
@@ -54,9 +55,6 @@ func testManager(manager oauth2.Manager) {
5455
So(accessToken, ShouldNotBeEmpty)
5556
So(refreshToken, ShouldNotBeEmpty)
5657

57-
_, err = manager.LoadAccessToken(code)
58-
So(err, ShouldNotBeNil)
59-
6058
ainfo, err := manager.LoadAccessToken(accessToken)
6159
So(err, ShouldBeNil)
6260
So(ainfo.GetClientID(), ShouldEqual, atParams.ClientID)

manage/manager.go

Lines changed: 99 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ func NewDefaultManager() *Manager {
2424

2525
// default config
2626
m.SetAuthorizeCodeExp(time.Minute * 10)
27-
m.SetImplicitTokenExp(time.Hour * 1)
28-
m.SetClientTokenExp(time.Hour * 2)
27+
m.SetImplicitTokenCfg(&Config{AccessTokenExp: time.Hour * 1})
28+
m.SetClientTokenCfg(&Config{AccessTokenExp: time.Hour * 2})
2929
m.SetAuthorizeCodeTokenCfg(&Config{IsGenerateRefresh: true, AccessTokenExp: time.Hour * 2, RefreshTokenExp: time.Hour * 24 * 3})
3030
m.SetPasswordTokenCfg(&Config{IsGenerateRefresh: true, AccessTokenExp: time.Hour * 2, RefreshTokenExp: time.Hour * 24 * 7})
3131

@@ -70,19 +70,24 @@ func (m *Manager) SetAuthorizeCodeTokenCfg(cfg *Config) {
7070
m.gtcfg[oauth2.AuthorizationCode] = cfg
7171
}
7272

73-
// SetImplicitTokenExp Set the implicit grant token expiration time
74-
func (m *Manager) SetImplicitTokenExp(exp time.Duration) {
75-
m.gtcfg[oauth2.Implicit] = &Config{AccessTokenExp: exp}
73+
// SetImplicitTokenCfg Set the implicit grant token config
74+
func (m *Manager) SetImplicitTokenCfg(cfg *Config) {
75+
m.gtcfg[oauth2.Implicit] = cfg
7676
}
7777

7878
// SetPasswordTokenCfg Set the password grant token config
7979
func (m *Manager) SetPasswordTokenCfg(cfg *Config) {
8080
m.gtcfg[oauth2.PasswordCredentials] = cfg
8181
}
8282

83-
// SetClientTokenExp Set the client grant token expiration time
84-
func (m *Manager) SetClientTokenExp(exp time.Duration) {
85-
m.gtcfg[oauth2.ClientCredentials] = &Config{AccessTokenExp: exp}
83+
// SetClientTokenCfg Set the client grant token config
84+
func (m *Manager) SetClientTokenCfg(cfg *Config) {
85+
m.gtcfg[oauth2.ClientCredentials] = cfg
86+
}
87+
88+
// SetRefreshTokenCfg Set the refreshing token config
89+
func (m *Manager) SetRefreshTokenCfg(cfg *Config) {
90+
m.gtcfg[oauth2.Refreshing] = cfg
8691
}
8792

8893
// MapTokenModel Mapping the token information model
@@ -179,28 +184,44 @@ func (m *Manager) GenerateAuthToken(rt oauth2.ResponseType, tgr *oauth2.TokenGen
179184
}
180185
_, ierr := m.injector.Invoke(func(ti oauth2.TokenInfo, gen oauth2.AuthorizeGenerate, tgen oauth2.AccessGenerate, stor oauth2.TokenStore) {
181186
ti = m.newTokenInfo(ti)
182-
var (
183-
tv string
184-
terr error
185-
)
187+
186188
td := &oauth2.GenerateBasic{
187189
Client: cli,
188190
UserID: tgr.UserID,
189191
CreateAt: time.Now(),
190192
}
191-
if rt == oauth2.Code {
192-
ti.SetAccessExpiresIn(m.codeExp)
193-
tv, terr = gen.Token(td)
194-
} else {
195-
ti.SetAccessExpiresIn(m.gtcfg[oauth2.Implicit].AccessTokenExp)
196-
tv, _, terr = tgen.Token(td, false)
197-
}
198-
if terr != nil {
199-
err = terr
200-
return
193+
switch rt {
194+
case oauth2.Code:
195+
tv, terr := gen.Token(td)
196+
if terr != nil {
197+
err = terr
198+
return
199+
}
200+
ti.SetCode(tv)
201+
ti.SetCodeExpiresIn(m.codeExp)
202+
ti.SetCodeCreateAt(td.CreateAt)
203+
if exp := tgr.AccessTokenExp; exp > 0 {
204+
ti.SetAccessExpiresIn(exp)
205+
}
206+
case oauth2.Token:
207+
tv, rv, terr := tgen.Token(td, m.gtcfg[oauth2.Implicit].IsGenerateRefresh)
208+
if terr != nil {
209+
err = terr
210+
return
211+
}
212+
ti.SetAccess(tv)
213+
ti.SetAccessCreateAt(td.CreateAt)
214+
aexp := m.gtcfg[oauth2.Implicit].AccessTokenExp
215+
if exp := tgr.AccessTokenExp; exp > 0 {
216+
aexp = exp
217+
}
218+
ti.SetAccessExpiresIn(aexp)
219+
if rv != "" && m.gtcfg[oauth2.Implicit].IsGenerateRefresh {
220+
ti.SetRefresh(rv)
221+
ti.SetRefreshCreateAt(td.CreateAt)
222+
ti.SetRefreshExpiresIn(m.gtcfg[oauth2.Implicit].RefreshTokenExp)
223+
}
201224
}
202-
ti.SetAccess(tv)
203-
ti.SetAccessCreateAt(td.CreateAt)
204225
ti.SetClientID(tgr.ClientID)
205226
ti.SetUserID(tgr.UserID)
206227
ti.SetRedirectURI(tgr.RedirectURI)
@@ -217,26 +238,58 @@ func (m *Manager) GenerateAuthToken(rt oauth2.ResponseType, tgr *oauth2.TokenGen
217238
return
218239
}
219240

241+
// get authorization code data
242+
func (m *Manager) getAuthorizationCode(code string) (info oauth2.TokenInfo, err error) {
243+
_, ierr := m.injector.Invoke(func(stor oauth2.TokenStore) {
244+
ti, terr := stor.GetByCode(code)
245+
if terr != nil {
246+
err = terr
247+
return
248+
} else if ti == nil {
249+
err = errors.ErrInvalidAuthorizeCode
250+
return
251+
} else if ti.GetCodeCreateAt().Add(ti.GetCodeExpiresIn()).Before(time.Now()) {
252+
err = errors.ErrInvalidAuthorizeCode
253+
return
254+
}
255+
info = ti
256+
})
257+
if ierr != nil && err == nil {
258+
err = ierr
259+
}
260+
return
261+
}
262+
263+
// delete authorization code data
264+
func (m *Manager) delAuthorizationCode(code string) (err error) {
265+
_, ierr := m.injector.Invoke(func(stor oauth2.TokenStore) {
266+
err = stor.RemoveByCode(code)
267+
})
268+
if ierr != nil && err == nil {
269+
err = ierr
270+
}
271+
return
272+
}
273+
220274
// GenerateAccessToken Generate the access token
221275
func (m *Manager) GenerateAccessToken(gt oauth2.GrantType, tgr *oauth2.TokenGenerateRequest) (accessToken oauth2.TokenInfo, err error) {
222276
if gt == oauth2.AuthorizationCode {
223-
ti, terr := m.LoadAccessToken(tgr.Code)
277+
ti, terr := m.getAuthorizationCode(tgr.Code)
224278
if terr != nil {
225-
if terr == errors.ErrInvalidAccessToken {
226-
err = errors.ErrInvalidAuthorizeCode
227-
return
228-
}
229279
err = terr
230280
return
231281
} else if ti.GetRedirectURI() != tgr.RedirectURI || ti.GetClientID() != tgr.ClientID {
232282
err = errors.ErrInvalidAuthorizeCode
233283
return
234-
} else if verr := m.RemoveAccessToken(tgr.Code); verr != nil { // remove authorize code
284+
} else if verr := m.delAuthorizationCode(tgr.Code); verr != nil {
235285
err = verr
236286
return
237287
}
238288
tgr.UserID = ti.GetUserID()
239289
tgr.Scope = ti.GetScope()
290+
if exp := ti.GetAccessExpiresIn(); exp > 0 {
291+
tgr.AccessTokenExp = exp
292+
}
240293
}
241294
cli, err := m.GetClient(tgr.ClientID)
242295
if err != nil {
@@ -262,13 +315,19 @@ func (m *Manager) GenerateAccessToken(gt oauth2.GrantType, tgr *oauth2.TokenGene
262315
ti.SetRedirectURI(tgr.RedirectURI)
263316
ti.SetScope(tgr.Scope)
264317
ti.SetAccessCreateAt(td.CreateAt)
265-
ti.SetAccessExpiresIn(m.gtcfg[gt].AccessTokenExp)
266318
ti.SetAccess(av)
267-
if m.gtcfg[gt].IsGenerateRefresh && rv != "" {
319+
320+
aexp := m.gtcfg[gt].AccessTokenExp
321+
if exp := tgr.AccessTokenExp; exp > 0 {
322+
aexp = exp
323+
}
324+
ti.SetAccessExpiresIn(aexp)
325+
if rv != "" && m.gtcfg[gt].IsGenerateRefresh {
268326
ti.SetRefreshCreateAt(td.CreateAt)
269327
ti.SetRefreshExpiresIn(m.gtcfg[gt].RefreshTokenExp)
270328
ti.SetRefresh(rv)
271329
}
330+
272331
err = stor.Create(ti)
273332
if err != nil {
274333
return
@@ -304,7 +363,11 @@ func (m *Manager) RefreshAccessToken(tgr *oauth2.TokenGenerateRequest) (accessTo
304363
UserID: ti.GetUserID(),
305364
CreateAt: time.Now(),
306365
}
307-
tv, _, terr := gen.Token(td, false)
366+
isGenRefresh := false
367+
if rcfg, ok := m.gtcfg[oauth2.Refreshing]; ok {
368+
isGenRefresh = rcfg.IsGenerateRefresh
369+
}
370+
tv, rv, terr := gen.Token(td, isGenRefresh)
308371
if terr != nil {
309372
err = terr
310373
return
@@ -314,6 +377,9 @@ func (m *Manager) RefreshAccessToken(tgr *oauth2.TokenGenerateRequest) (accessTo
314377
if scope := tgr.Scope; scope != "" {
315378
ti.SetScope(scope)
316379
}
380+
if rv != "" {
381+
ti.SetRefresh(rv)
382+
}
317383
if verr := stor.Create(ti); verr != nil {
318384
err = verr
319385
return

model.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ type (
3434
// Set Scope of authorization
3535
SetScope(string)
3636

37+
// Get Authorization code
38+
GetCode() string
39+
// Set Authorization code
40+
SetCode(string)
41+
// Get Create Time
42+
GetCodeCreateAt() time.Time
43+
// Set Create Time
44+
SetCodeCreateAt(time.Time)
45+
// Get The lifetime in seconds of the authorization code
46+
GetCodeExpiresIn() time.Duration
47+
// Set The lifetime in seconds of the authorization code
48+
SetCodeExpiresIn(time.Duration)
49+
3750
// Get Access Token
3851
GetAccess() string
3952
// Set Access Token

0 commit comments

Comments
 (0)