Skip to content

Commit

Permalink
Add refresh uri setting (p2#330)
Browse files Browse the repository at this point in the history
  • Loading branch information
fotiDim authored and ossus-lib committed Nov 6, 2019
1 parent 8a035f7 commit 34c8c38
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 2 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Contributors

Contributors to the codebase, in reverse chronological order:

- Foti Dim, @fotidim
- Larry Brunet, @larrybrunet
- Dave Carlson, @drdavec
- Sam Oakley, @blork
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ oauth2.authConfig.authorizeEmbedded = true
oauth2.authConfig.authorizeContext = <# your UIViewController / NSWindow #>
```

Need to specify a separate refresh token URI? You can set the `refresh_uri` in the Settings Dictionary. If specified the library will refresh access tokens using the `refresh_uri` you specified, otherwise it will use the `token_uri`.

Need to debug? Use a `.debug` or even a `.trace` logger:

```swift
Expand Down Expand Up @@ -543,4 +545,3 @@ Since there is no `NOTICE` file there is nothing that you have to include in you


[sample]: https://github.com/p2/OAuth2App

1 change: 1 addition & 0 deletions Sources/Base/OAuth2Base.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ open class OAuth2Base: OAuth2Securable {
- client_secret (String), usually only needed for code grant
- authorize_uri (URL-String)
- token_uri (URL-String), if omitted the authorize_uri will be used to obtain tokens
- refresh_uri (URL-String), if omitted the token_uri will be used to obtain tokens
- redirect_uris (Array of URL-Strings)
- scope (String)

Expand Down
6 changes: 6 additions & 0 deletions Sources/Base/OAuth2ClientConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ open class OAuth2ClientConfig {

/// The URL where we can exchange a code for a token.
public final var tokenURL: URL?

/// The URL where we can refresh an access token using a refresh token.
public final var refreshURL: URL?

/// Where a logo/icon for the app can be found.
public final var logoURL: URL?
Expand Down Expand Up @@ -112,6 +115,9 @@ open class OAuth2ClientConfig {
if let token = settings["token_uri"] as? String {
tokenURL = URL(string: token)
}
if let refresh = settings["refresh_uri"] as? String {
refreshURL = URL(string: refresh)
}
if let registration = settings["registration_uri"] as? String {
registrationURL = URL(string: registration)
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/Flows/OAuth2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ open class OAuth2: OAuth2Base {
- client_secret (String), usually only needed for code grant
- authorize_uri (URL-String)
- token_uri (URL-String), if omitted the authorize_uri will be used to obtain tokens
- refresh_uri (URL-String), if omitted the token_uri will be used to obtain tokens
- redirect_uris (Array of URL-Strings)
- scope (String)

Expand Down Expand Up @@ -343,7 +344,7 @@ open class OAuth2: OAuth2Base {
throw OAuth2Error.noRefreshToken
}

let req = OAuth2AuthRequest(url: (clientConfig.tokenURL ?? clientConfig.authorizeURL))
let req = OAuth2AuthRequest(url: (clientConfig.refreshURL ?? clientConfig.tokenURL ?? clientConfig.authorizeURL))
req.params["grant_type"] = "refresh_token"
req.params["refresh_token"] = refreshToken
if let clientId = clientId {
Expand Down
28 changes: 28 additions & 0 deletions Tests/BaseTests/OAuth2Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ class OAuth2Tests: XCTestCase {
"keychain": false,
])
}

func refreshOAuth2() -> OAuth2 {
return OAuth2(settings: [
"client_id": "abc",
"authorize_uri": "https://auth.ful.io",
"token_uri": "https://token.ful.io",
"refresh_uri": "https://refresh.ful.io",
"scope": "login",
"verbose": true,
"keychain": false,
])
}

func testInit() {
var oauth = OAuth2(settings: ["client_id": "def"])
Expand Down Expand Up @@ -88,6 +100,22 @@ class OAuth2Tests: XCTestCase {
//XCTAssertEqual(params["redirect_uri"]!, "oauth2app://callback", "Expecting correct `redirect_uri` in query")
XCTAssertNil(params["state"], "Expecting no `state` in query")
}

func testTokenRefreshRequest() {
let oa = refreshOAuth2()
oa.verbose = false
oa.clientConfig.refreshToken = "abc"
let req = try! oa.tokenRequestForTokenRefresh().asURLRequest(for: oa)
let auth = req.url!

let comp = URLComponents(url: auth, resolvingAgainstBaseURL: true)!
XCTAssertEqual("https", comp.scheme!, "Need correct scheme")
XCTAssertEqual("refresh.ful.io", comp.host!, "Need correct host")

let params = OAuth2.params(fromQuery: comp.percentEncodedQuery ?? "")
//XCTAssertEqual(params["redirect_uri"]!, "oauth2app://callback", "Expecting correct `redirect_uri` in query")
XCTAssertNil(params["state"], "Expecting no `state` in query")
}

func testAuthorizeCall() {
let oa = genericOAuth2()
Expand Down
32 changes: 32 additions & 0 deletions Tests/FlowTests/OAuth2RefreshTokenTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ class OAuth2RefreshTokenTests: XCTestCase {
"keychain": false,
])
}

func refreshOAuth2() -> OAuth2 {
return OAuth2(settings: [
"client_id": "abc",
"authorize_uri": "https://auth.ful.io",
"token_uri": "https://token.ful.io",
"refresh_uri": "https://refresh.ful.io",
"keychain": false,
])
}

func testCannotRefresh() {
let oauth = genericOAuth2()
Expand Down Expand Up @@ -76,6 +86,28 @@ class OAuth2RefreshTokenTests: XCTestCase {
XCTAssertNil(dict["client_secret"])
XCTAssertNil(req!.allHTTPHeaderFields?["Authorization"])
}

func testRefreshRequestWithDedicatedRefreshURI() {
let oauth = refreshOAuth2()
oauth.clientConfig.refreshToken = "pov"

let req = try? oauth.tokenRequestForTokenRefresh().asURLRequest(for: oauth)
XCTAssertNotNil(req)
XCTAssertNotNil(req?.url)
XCTAssertNotNil(req?.httpBody)
XCTAssertEqual("https://refresh.ful.io", req!.url!.absoluteString)
let comp = URLComponents(url: req!.url!, resolvingAgainstBaseURL: true)
let params = comp?.percentEncodedQuery
XCTAssertNil(params)
let body = String(data: req!.httpBody!, encoding: String.Encoding.utf8)
XCTAssertNotNil(body)
let dict = OAuth2.params(fromQuery: body!)
XCTAssertEqual(dict["client_id"], "abc")
XCTAssertEqual(dict["refresh_token"], "pov")
XCTAssertEqual(dict["grant_type"], "refresh_token")
XCTAssertNil(dict["client_secret"])
XCTAssertNil(req!.allHTTPHeaderFields?["Authorization"])
}

func testRefreshRequestWithSecret() {
let oauth = genericOAuth2()
Expand Down

0 comments on commit 34c8c38

Please sign in to comment.