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
21 changes: 14 additions & 7 deletions .github/workflows/docc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,23 @@ jobs:
- uses: actions/checkout@v4
- name: Select Xcode
run: sudo xcode-select -s "/Applications/$XCODE_VERSION.app"
- name: Generate DocC
run: xcodebuild docbuild -scheme OAuthKit -derivedDataPath /tmp/docbuild -destination 'generic/platform=macOS';
- name: Transform DocC
- name: Add Plugin Dependency
run: swift package add-dependency "https://github.com/apple/swift-docc-plugin" --branch main
- name: Generate Documentation
run: |
$(xcrun --find docc) process-archive \
transform-for-static-hosting /tmp/docbuild/Build/Products/Debug/OAuthKit.doccarchive \
swift package \
--allow-writing-to-package-directory \
--allow-writing-to-directory ${{github.workspace}}/docs \
generate-documentation \
--target OAuthKit \
--transform-for-static-hosting \
--hosting-base-path OAuthKit \
--output-path docs;
--output-path ${{github.workspace}}/docs \
--source-service github \
--source-service-base-url https://github.com/codefiesta/OAuthKit/blob/main \
--checkout-path ${{github.workspace}};
- name: Update Index
run: echo "<script>window.location.href += \"/documentation/oauthkit\"</script>" > docs/index.html;
run: echo "<script>window.location.href += \"/documentation/oauthkit\"</script>" > ${{github.workspace}}/docs/index.html;
- name: Upload Pages Artifact
uses: actions/upload-pages-artifact@v3
with:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ OAuthKit is a contemporary, event-driven Swift Package that utilizes the [Observ

## OAuthKit Features

OAuthKit is a small, lightweight package that provides out of the box [Swift Concurrency](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/) safety support and [Observable](https://github.com/codefiesta/OAuthKit/blob/main/Sources/OAuthKit/OAuth.swift#L36) OAuth 2.0 state events that allow fine grained control over when and how to start authorization flows.
OAuthKit is a small, lightweight package that provides out of the box [Swift Concurrency](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/) safety support and [Observable](https://codefiesta.github.io/OAuthKit/documentation/oauthkit/oauth/state-swift.enum) OAuth 2.0 state events that allow fine grained control over when and how to start authorization flows.

Key features include:

- [Simple Configuration](#oauthkit-configuration)
- [Keychain protection with biometrics or companion device](#oauth-initialized-with-keychain-protection-and-private-browsing)
- [Private Browsing with non-persistent WebKit Datastores](#oauth-initialized-with-keychain-protection-and-private-browsing)
- [Custom URLSession](#oauth-initialized-with-keychain-protection-and-private-browsing) configuration for complete control custom protocol specific data
- [Observable State](https://github.com/codefiesta/OAuthKit/blob/main/Sources/OAuthKit/OAuth.swift#L36) driven events to allow full control over when and if users are prompted to authenticate with an OAuth provider
- [Keychain protection with biometrics or companion device](https://codefiesta.github.io/OAuthKit/documentation/oauthkit/configuration#Keychain-Protection)
- [Private Browsing with non-persistent WebKit Datastores](https://codefiesta.github.io/OAuthKit/documentation/oauthkit/configuration#Private-Browsing)
- [Custom URLSession](https://codefiesta.github.io/OAuthKit/documentation/oauthkit/configuration#URL-Session) configuration for complete control custom protocol specific data
- [Observable State](https://codefiesta.github.io/OAuthKit/documentation/oauthkit/gettingstarted#Observing-OAuth-State) driven events to allow full control over when and if users are prompted to authenticate with an OAuth provider
- Supports all Apple Platforms (iOS, macOS, tvOS, visionOS, watchOS)
- [Support for every OAuth 2.0 Flow](#oauthkit-configuration)
- [Authorization Code](#oauth-20-authorization-code-flow)
Expand Down Expand Up @@ -160,7 +160,7 @@ struct ContentView: View {
```

## 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 [Environment](https://developer.apple.com/documentation/swiftui/environment) property wrapper. You can find an example `oauth.json` file [here](https://github.com/codefiesta/OAuthKit/blob/main/Tests/OAuthKitTests/Resources/oauth.json). OAuthKit provides flexible constructor options that allows developers to customize how their oauth client is initialized and what features they want to implement. See the [oauth.init(\_:bundle:options)](https://github.com/codefiesta/OAuthKit/blob/main/Sources/OAuthKit/OAuth.swift#L98) method for details.
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 [Environment](https://developer.apple.com/documentation/swiftui/environment) property wrapper. You can find an example `oauth.json` file [here](https://github.com/codefiesta/OAuthKit/blob/main/Tests/OAuthKitTests/Resources/oauth.json). OAuthKit provides flexible constructor options that allows developers to customize how their oauth client is initialized and what features they want to implement. See the [oauth.init(\_:bundle:options)](https://codefiesta.github.io/OAuthKit/documentation/oauthkit/oauth) method for details.

### OAuth initialized from main bundle (default)
```swift
Expand Down Expand Up @@ -222,7 +222,7 @@ let oauth: OAuth = .init(.main, options: options)
```

## OAuthKit Authorization Flows
OAuth 2.0 authorization flows are started by calling the [oauth.authorize(provider:grantType:)](https://github.com/codefiesta/OAuthKit/blob/main/Sources/OAuthKit/OAuth.swift#L117) method.
OAuth 2.0 authorization flows are started by calling the [oauth.authorize(provider:grantType:)](https://codefiesta.github.io/OAuthKit/documentation/oauthkit/oauth#Starting-an-authorization-flow) method.

A good resource to help understand the detailed steps involved in OAuth 2.0 authorization flows can be found on the [OAuth 2.0 Playground](https://www.oauth.com/playground/index.html).

Expand Down
37 changes: 0 additions & 37 deletions Sources/OAuthKit/OAuth+State.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,6 @@ import Foundation
extension OAuth {

/// Holds the OAuth state that is published to subscribers via the ``state`` property.
///
/// A n example of observing the ``state`` property in SwiftUI:
/// ```swift
///struct ContentView: View {
///
/// @Environment(\.oauth)
/// var oauth: OAuth
///
/// var body: some View {
/// VStack {
/// switch oauth.state {
/// case .empty:
/// providerList
/// case .authorizing(let provider, let grantType):
/// Text("Authorizing [\(provider.id)] with [\(grantType.rawValue)]")
/// case .requestingAccessToken(let provider):
/// Text("Requesting Access Token [\(provider.id)]")
/// case .requestingDeviceCode(let provider):
/// Text("Requesting Device Code [\(provider.id)]")
/// case .authorized(let provider, _):
/// Button("Authorized [\(provider.id)]") {
/// oauth.clear()
/// }
/// case .receivedDeviceCode(_, let deviceCode):
/// Text("To login, visit")
/// Text(.init("[\(deviceCode.verificationUri)](\(deviceCode.verificationUri))"))
/// .foregroundStyle(.blue)
/// Text("and enter the following code:")
/// Text(deviceCode.userCode)
/// }
/// }
/// .onChange(of: oauth.state) { oldState, newState in
/// handle(state: newState)
/// }
/// }
/// }
/// ```
public enum State: Equatable, Sendable {

/// The state is empty and no authorizations or tokens have been issued.
Expand Down
48 changes: 48 additions & 0 deletions Sources/OAuthKit/OAuthKit.docc/Extensions/State.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# ``OAuthKit/OAuth/State``

@Metadata {
@Available(iOS, introduced: "18.0")
@Available(macOS, introduced: "15.0")
@Available(tvOS, introduced: "18.0")
@Available(visionOS, introduced: "2.0")
@Available(watchOS, introduced: "11.0")
}

## Overview
An example of observing the ``state`` property in SwiftUI:

```swift
struct ContentView: View {

@Environment(\.oauth)
var oauth: OAuth

var body: some View {
VStack {
switch oauth.state {
case .empty:
providerList
case .authorizing(let provider, let grantType):
Text("Authorizing [\(provider.id)] with [\(grantType.rawValue)]")
case .requestingAccessToken(let provider):
Text("Requesting Access Token [\(provider.id)]")
case .requestingDeviceCode(let provider):
Text("Requesting Device Code [\(provider.id)]")
case .authorized(let provider, _):
Button("Authorized [\(provider.id)]") {
oauth.clear()
}
case .receivedDeviceCode(_, let deviceCode):
Text("To login, visit")
Text(.init("[\(deviceCode.verificationUri)](\(deviceCode.verificationUri))"))
.foregroundStyle(.blue)
Text("and enter the following code:")
Text(deviceCode.userCode)
}
}
.onChange(of: oauth.state) { oldState, newState in
handle(state: newState)
}
}
}
```
1 change: 1 addition & 0 deletions Sources/OAuthKit/OAuthKit.docc/OAuthKit.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ This has the advantage of avoiding direct coupling with an authorization flow, e
- ``OAuth/GrantType``

### State Observability
- ``OAuth/State``
- ``OAuth/state``