Skip to content
Merged
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
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,27 @@ struct ContentView: View {
switch oauth.state {
case .empty:
providerList
case .authorizing(let provider):
case .authorizing(let provider, _):
Text("Authorizing [\(provider.id)]")
case .requestingAccessToken(let provider):
Text("Requesting Access Token [\(provider.id)]")
case .requestingDeviceCode(let provider):
Text("Requesting Device Code [\(provider.id)]")
case .authorized(let auth):
Button("Authorized [\(auth.provider.id)]") {
oauth.clear()
}
case .receivedDeviceCode(_, let deviceCode):
Text("To login, visit")
Text(deviceCode.verificationUri).foregroundStyle(.blue)
Text("and enter the following code:")
Text(deviceCode.userCode)
.padding()
.border(Color.primary)
.font(.title)
}
}
.onChange(of: oauth.state) { state, _ in
.onChange(of: oauth.state) { _, state in
handle(state: state)
}
}
Expand All @@ -69,8 +79,8 @@ struct ContentView: View {
var providerList: some View {
List(oauth.providers) { provider in
Button(provider.id) {
// Start the authorization flow
oauth.authorize(provider: provider)
// Start the authorization flow (use .deviceCode for tvOS)
oauth.authorize(provider: provider, grantType: .authorizationCode)
}
}
}
Expand All @@ -79,16 +89,22 @@ struct ContentView: View {
/// - Parameter state: the published state change
private func handle(state: OAuth.State) {
switch state {
case .empty, .requestingAccessToken:
case .empty, .requestingAccessToken, .requestingDeviceCode:
break
case .authorizing(let provider):
case .authorizing, .receivedDeviceCode:
openWindow(id: "oauth")
case .authorized(_):
dismissWindow(id: "oauth")
}
}
}
```
## tvOS (Device Authorization Grant)
OAuthKit supports the [OAuth 2.0 Device Authorization Grant](https://alexbilbie.github.io/2016/04/oauth-2-device-flow-grant/), which is used by apps that don't have access to a web browser (like tvOS). To leverage OAuthKit in tvOS apps, simply add the `deviceCodeURL` to your [OAuth.Provider](https://github.com/codefiesta/OAuthKit/blob/main/Sources/OAuthKit/OAuth.swift#L64) and initialize the device authorization grant workflow by calling ```oauth.authorize(provider: provider, grantType: .deviceCode)```

![tvOS-screenshot](https://github.com/user-attachments/assets/14997164-f86a-4ee0-b6b7-8c0d9732c83e)


## OAuthKit Configuration
By default, the easiest way to configure OAuthKit is to simply drop an `oauth.json` file into your main bundle and it will get automatically loaded into your swift application and available as an [EnvironmentObject](https://developer.apple.com/documentation/swiftui/environmentobject). You can find an example `oauth.json` file [here](https://github.com/codefiesta/OAuthKit/blob/main/Tests/OAuthKitTests/Resources/oauth.json).

Expand Down
2 changes: 1 addition & 1 deletion Sources/OAuthKit/Extensions/URLRequest+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public extension URLRequest {
switch oath.state {
case .authorized(let auth):
addValue("\(bearer) \(auth.token.accessToken)", forHTTPHeaderField: authHeader)
case .empty, .authorizing, .requestingAccessToken:
case .empty, .authorizing, .requestingAccessToken, .requestingDeviceCode, .receivedDeviceCode:
debugPrint("⚠️ [OAuth is not authorized]")
}
}
Expand Down
28 changes: 28 additions & 0 deletions Sources/OAuthKit/Extensions/URLResponse+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// URLResponse+Extensions.swift
// OAuthKit
//
// Created by Kevin McKee
//

import Foundation

public extension URLResponse {

/// Returns true if the response status code is in the 200's.
var isOK: Bool {
if let code = statusCode() {
return 200...299 ~= code
}
return false
}

/// Extracts the status code from the response.
func statusCode() -> Int? {
if let httpResponse = self as? HTTPURLResponse {
return httpResponse.statusCode
}
return nil
}
}

Loading