Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit d79e2a1

Browse files
committed
Documentation Fixes
1 parent 08b7fb1 commit d79e2a1

432 files changed

Lines changed: 794 additions & 67 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
# SwAuth
22

3-
SwAuth is a OAuth 2.0 library for iOS 15.0+, macOS 12.0+, watchOS 8.0+, and tvOS 15.0+ written in Swift.
3+
SwAuth is an OAuth 2.0 HTTP request library for written in Swift iOS 15.0+, macOS 12.0+, watchOS 8.0+, and tvOS 15.0+.
44

55
## Features
66

77
- [x] Usable and beautiful syntax with async/await! Say goodbye to completion handler hell!
8-
- [x] Authorization Code Grant (RFC 6749/6750), Proof Key for Code Exchange (PKCE) extension for Authorization Code Grant (RFC 7636), and the Device Authorization Grant (RFC 8628).
8+
- [x] Supports Authorization Code Grant (RFC 6749/6750), Proof Key for Code Exchange (PKCE) extension for Authorization Code Grant (RFC 7636), and the Device Authorization Grant (RFC 8628).
99
- [x] Support for all Apple platforms.
1010
- [x] Retry errored requests.
11-
- [x] Built on [SwiftNIO](https://github.com/apple/swift-nio) with [AsyncHTTPClient](https://github.com/swift-server/async-http-client). (Suck it URLSession)
12-
- [x] [Complete. Meticulous. Thorough. documentation 😰.](https://swauth.netlify.app/documentation/Swauth)
13-
- [x] Device Authorization QR Code for tvOS/watchOS.
11+
- [x] Automatically refreshes tokens.
12+
- [x] Tokens stored on Keychain, cross-site request forgery mitigation with state by default.
13+
- [x] Easily deal with JSON responses with built-in [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON).
1414
- [x] Easily integrate with SwiftUI.
15+
- [x] [Complete, Meticulous, Thorough, documentation.](https://swauth.netlify.app/documentation/Swauth)
16+
- [x] Errors that are actually useful... well most of the time.
17+
- [x] Built on [SwiftNIO](https://github.com/apple/swift-nio) with [AsyncHTTPClient](https://github.com/swift-server/async-http-client).
18+
- [x] QR Code for the Device Authorization Flow (tvOS/watchOS).
1519
- [x] Sample/Example Apps.
16-
- [x] Automatically refresh tokens.
17-
- [x] Tokens securely stored on the Keychain.
18-
- [x] Easily deal with JSON responses.
19-
- [x] Useful errors (mostly).
2020

2121
## Requirments
2222

@@ -25,7 +25,7 @@ SwAuth is a OAuth 2.0 library for iOS 15.0+, macOS 12.0+, watchOS 8.0+, and tvOS
2525

2626
## Installation/Integration
2727

28-
Use the Swift Package Manager to add SwAuth to your project! Simply add the package to your dependencies in your `Package.swift`:
28+
Use the Swift Package Manager to add SwAuth to your project! Simply add the package to dependencies in your `Package.swift`:
2929

3030
```swift
3131
let package = Package(
@@ -36,11 +36,89 @@ let package = Package(
3636
)
3737
```
3838

39-
## Usage
39+
## Basic Usage
4040

4141
1. Import SwAuth in files you wish to use it's amazing features:
4242
```swift
4343
import SwAuth
4444
```
4545

46-
2. Read the docs 🤣 [https://swauth.netlify.app/documentation/Swauth](https://swauth.netlify.app/documentation/Swauth)
46+
2. Create an instance of keychain:
47+
48+
```swift
49+
let keychain = Keychain(service: "com.your.bundleID",
50+
accessGroup: "appIdentifierPrefix.com.your.bundleID").label("Your App Name")
51+
```
52+
53+
3. Create an instance of the proper authorization flow for your Web API.
54+
55+
```swift
56+
let keychain = Keychain(service: "com.your.bundleID",
57+
accessGroup: "appIdentifierPrefix.com.your.bundleID").label("Your App Name")
58+
59+
let spotify = AuthorizationCodeFlow(clientID: "YourClientID",
60+
authorizationEndpoint: URL(string: "https://accounts.spotify.com/authorize")!,
61+
tokenEndpoint: URL(string: "https://accounts.spotify.com/api/token")!,
62+
redirectURI: "someapp://callback",
63+
keychain: keychain,
64+
scopes: "user-follow-modify")
65+
```
66+
67+
4. Start an ASWebAuthenticationSession like in the [example app](https://github.com/Colaski/SwAuth/blob/main/SwAuthTestApp/SwAuthTestApp/ProviderView.swift#L94) with the instance's authorization URL:
68+
69+
```swift
70+
spotify.authorizationURL
71+
```
72+
73+
5. Pass the callback URL from the ASWebAuthenticationSession into the provided handler method:
74+
75+
```swift
76+
do {
77+
try await spotify.authorizationResponseHandler(for: callbackURL)
78+
} catch {
79+
print(error.localizedDescription)
80+
}
81+
```
82+
83+
6. Make an authorized request:
84+
85+
```swift
86+
do {
87+
// https://developer.spotify.com/documentation/web-api/reference/#/operations/follow-artists-users
88+
var request = HTTPRequest(endpoint: URL(sting: "https://api.spotify.com/v1/me/following")!)
89+
request.httpMethod = .PUT
90+
request.endpointQueryItems = ["type": "artist"]
91+
request.httpBody = ["ids": ["5K4W6rqBFWDnAN6FQUkS6x"]]
92+
request.bodyEncoding = .JSON
93+
94+
// Send an authenticated HTTP request, this one will follow the artist Kanye on Spotify.
95+
let json = try await spotify.authenticatedRequest(for: request, numberOfRetries: 2).json()
96+
97+
// Prints the JSON output
98+
print(json)
99+
} catch {
100+
print(error.localizedDescription)
101+
}
102+
```
103+
104+
For more information, read my beautiful documentation: [https://swauth.netlify.app/documentation/Swauth](https://swauth.netlify.app/documentation/Swauth)
105+
106+
## Contributing
107+
108+
Contributions are welcome!
109+
110+
Make sure swift is installed and then
111+
```bash
112+
git clone https://github.com/Colaski/SwAuth.git
113+
cd SwAuth
114+
swift build
115+
```
116+
117+
Make your changes and submit and a PR for review!
118+
119+
Nice to have list:
120+
121+
- [ ] Include ready to go implementations of Web API's with endpoints like in the [exmaple app](https://github.com/Colaski/SwAuth/blob/main/SwAuthTestApp/SwAuthTestApp/Spotify.swift)
122+
- Perhaps Spotify, Google, Azure/Microsoft, Github etc.
123+
124+
- [ ] OAuth1 support

Sources/SwAuth/AuthorizationCodeFlow.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import enum NIOHTTP1.HTTPMethod
2929
/**
3030
The OAuth 2.0 Authorization Code Grant according to RFC 6749/6750.
3131

32-
- Warning: The OAuth 2.0 Authorization Code Flow is not secure for client side applications, it should only be
32+
- Warning: The OAuth 2.0 Authorization Code Flow is not secure for native applications, it should only be
3333
used when ABSOLUTELY NECESSARY. If you are connecting to your own HTTP server, please implement RFC 7636
3434
and utilize the ``PKCEAuthorizationFlow``. Unfortunately, if you do not have control over the server,
3535
this may be your only option.
@@ -129,7 +129,7 @@ open class AuthorizationCodeFlow: Swauthable {
129129
/// See ``tokenRequestParams`` for the provided parameters.
130130
open var additionalTokenRequestParams: [String: String]?
131131

132-
/// **Ignore if the web API does not provide a refresh token.**
132+
/// **Ignore if the Web API does not provide a refresh token.**
133133
/// Any additional HTTP body parameters for the token refresh request. The key/value pairs for
134134
/// "refresh\_token" and "grant\_type" are handled internally when a
135135
/// ``Swauthable/authenticatedRequest(for:numberOfRetries:)``
@@ -142,7 +142,7 @@ open class AuthorizationCodeFlow: Swauthable {
142142
/// Some servers may use a different key for their authorization header's token type than the one
143143
/// provided by the token request response.
144144
///
145-
/// For example, ``Github`` uses "token", however their token response type is "bearer".
145+
/// For example, Github uses "token", however their token response type is "bearer".
146146
open var authHeaderTokenType: String?
147147

148148
/// Some servers may allow or want the client id and client secret to be parameters in a HTTP request's

Sources/SwAuth/DeviceAuthorizationFlow.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ open class DeviceAuthorizationFlow: Swauthable {
117117
/// Some APIs may use a different key for their authorization header's token type than the one
118118
/// provided by the token request response.
119119
///
120-
/// For example, ``Github`` uses "token", however their token response type is "bearer".
120+
/// For example, Github uses "token", however their token response type is "bearer".
121121
open var authHeaderTokenType: String?
122122

123123
/// The ``DeviceFlowAuthResponse-swift.struct``from a call to the

Sources/SwAuth/Globals.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fileprivate let httpClient = HTTPClient(
3939
internal func http(request: HTTPRequest) async throws -> HTTPRequest.Response {
4040
let httpRequest = try Request(from: request)
4141
var deadline: NIODeadline? {
42-
return request.terminateAfter != nil ? .now() + request.terminateAfter! : nil
42+
return request.timeoutAfter != nil ? .now() + request.timeoutAfter! : nil
4343
}
4444

4545
return try await withCheckedThrowingContinuation { continuation in

Sources/SwAuth/HTTPRequest.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ HTTP load request.
3434
*/
3535
public struct HTTPRequest {
3636
// MARK: - Properties
37-
/// The server endpoint to which the HTTP request will be sent. Is initialized.
38-
public var endpoint: URL
37+
/// The server endpoint URL to which the HTTP request will be sent. Is initialized.
38+
public let endpoint: URL
3939
/// Query items to add to the endpoint URL.
4040
public var endpointQueryItems: [String: String]?
4141

@@ -58,14 +58,16 @@ public struct HTTPRequest {
5858
/// Any additional HTTP header values besides "Authentication" and "Content-Type".
5959
public var additionalHTTPHeaders: [String: String]?
6060

61-
/// Set the amount of time allowed for the request to complete before it terminates.
61+
/// Set the amount of time allowed for the request to complete before it times out.
6262
///
6363
/// By default, all requests are set to automatically timeout after 5 seconds of attempting to connect. Setting this property
6464
/// will void that default behavior. If the request has not been completed after the amount of time set by this property, it
6565
/// will terminate.
6666
///
67-
/// example: `.seconds(10)`
68-
public var terminateAfter: TimeAmount?
67+
/// Suppports nanoseconds, microseconds, milliseconds, seconds, minutes, hours.
68+
///
69+
/// examples: `.seconds(10)`
70+
public var timeoutAfter: TimeAmount?
6971

7072
// MARK: - Method
7173
/// Returns the httpBody as Data and with the proper encoding specified by
@@ -97,7 +99,7 @@ public struct HTTPRequest {
9799
/// See Also:
98100
/// - ``init(endpoint:withBody:bodyEncoding:)``
99101
///
100-
/// - Parameter endpoint: The server endpoint to which the HTTP request will be sent.
102+
/// - Parameter endpoint: The server endpoint URL to which the HTTP request will be sent.
101103
public init(endpoint: URL) {
102104
self.endpoint = endpoint
103105
}
@@ -106,7 +108,7 @@ public struct HTTPRequest {
106108
/// Calls ``init(endpoint:)``, and also initializes ``httpBody`` and ``bodyEncoding``.
107109
///
108110
/// - Parameters:
109-
/// - endpoint: The server endpoint to which the HTTP request will be sent.
111+
/// - endpoint: The server endpoint URL to which the HTTP request will be sent.
110112
/// - withBody: The body of the HTTP request.
111113
/// - bodyEncoding: The ``RequestBodyEncoding`` type of the request body.
112114
public init(endpoint: URL,

Sources/SwAuth/PKCEAuthorizationFlow.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ open class PKCEAuthorizationFlow: Swauthable {
139139
/// See ``tokenRequestParams`` for the provided parameters.
140140
open var additionalTokenRequestParams: [String: String]?
141141

142-
/// **Ignore if the web API does not provide a refresh token.**
142+
/// **Ignore if the Web API does not provide a refresh token.**
143143
/// Any additional HTTP body parameters for the token refresh request. The key/value pairs for
144144
/// "refresh\_token" and "grant\_type" are handled internally when a
145145
/// ``Swauthable/authenticatedRequest(for:numberOfRetries:)``
@@ -149,7 +149,7 @@ open class PKCEAuthorizationFlow: Swauthable {
149149
/// Some servers may use a different key for their authorization header's token type than the one
150150
/// provided by the token request response.
151151
///
152-
/// For example, ``Github`` uses "token", however their token response type is "bearer".
152+
/// For example, Github uses "token", however their token response type is "bearer".
153153
open var authHeaderTokenType: String?
154154

155155
// MARK: - Methods

Sources/SwAuth/SwAuth Documentation.docc/AuthorizationCodeFlow.md

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

33
## Getting Started
44

5-
To use the Authorization Code Flow, first create an instance of Keychain and then create an instance of AuthorizationCodeFlow by filling in the information of the WebAPI you wish to utilize. Spotify will be used as an example.
5+
To use the Authorization Code Flow, first create an instance of Keychain and then create an instance of AuthorizationCodeFlow by filling in the information of the Web API you wish to utilize. Spotify will be used as an example.
66

77
```swift
88
let keychain = Keychain(service: "com.your.bundleID",
@@ -22,7 +22,7 @@ I can now get the authorization URL my user will follow like so:
2222
let authURL = spotify.authorizationURL
2323
```
2424

25-
SwiftUI users, I recommend using [BetterSafariView](https://github.com/stleamist/BetterSafariView) for following the authorization URL.
25+
SwiftUI users, I recommend using [BetterSafariView's](https://github.com/stleamist/BetterSafariView) ASWebAuthenticationSession for following the authorization URL.
2626

2727
Assuming the user authorizes your application, pass the callback URL into ``authorizationResponseHandler(for:)`` (but of course take into account proper error handling):
2828

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Choosing the Right Authorization Flow.
2+
3+
SwAuth provides 3 different OAuth 2.0 authorization flows to use: ``AuthorizationCodeFlow``, ``PKCEAuthorizationFlow``, and ``DeviceAuthorizationFlow``. Choosing which one to use and in what context can be difficult.
4+
5+
## AuthorizationCodeFlow
6+
7+
The ``AuthorizationCodeFlow`` is the most widely supported OAuth 2.0 flow since it is the basic OAuth 2.0 specification. It is used for devices that are not input-constrained (like on iOS, iPadOS, and macOS). However, it should be avoided if at all possible. As the warning I wrote in it's respective documentation states, "The OAuth 2.0 Authorization Code Flow is not secure for native applications, it should only be used when ABSOLUTELY NECESSARY." The reason for this is that in a native app the client secret is included in the source, which you are compiling and distributing. Strings can be pretty easily extracted from compiled binaries, giving someone access to your client secret. Knowing the client secret would allow an attacker to exchange an intercepted authorization code for a token, giving the attacker access to your user's account 😳.
8+
9+
Thus, if you are using SwAuth to send authorized requests to your server please implement [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636). I'm sure there is a library or framework that implements it for whatever language you are using server-side ([here's one for Node.js](https://github.com/panva/node-oidc-provider)). If it is not your server, contact the owner and ask about implementing PKCE. If all else fails you may be forced to use the ``AuthorizationCodeFlow``, in which case I'd recommend using some sort of obfuscation and encryption technique for the client secret (at a minimum don't just have a client secret as a plain string). Obfuscation isn't very secure but it's better than nothing.
10+
11+
## PKCEAuthorizationFlow
12+
13+
Much like the AuthorizationCodeFlow, the ``PKCEAuthorizationFlow`` is used for devices that are not input-constrained (like iOS, iPadOS, and macOS). Unlike the AuthorizationCodeFlow, the PKCE Authorization Code Flow is safe for use in native applications (the spec was created for such purpose). No need to provide the client secret, with PKCE (Proof Key for Code Exchange) an attacker in possesion of an intercepted Authorization Code can't exchange it for a token unless they have the on-device-cryptographically-generated code verifer.
14+
15+
The downside is that the Proof Key for Code Exchange extension to the OAuth 2.0 Authorization Code Grant needs to be supported by the Web API you are trying to send requests to. If you own the server, great! implement [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636) and/or find a server-side framework or library that implements it ([again, here's one for Node.js](https://github.com/panva/node-oidc-provider)). Otherwise, ask the owner to implement it.
16+
17+
## DeviceAuthorizationFlow
18+
19+
The ``DeviceAuthorizationFlow`` is used for use on devices that are input-constrained (like watchOS and tvOS). If the Web API you are trying to send requests to does not support the Device Authorization Grant ask the owner. If you own the server implement it or use a server-side library/framework that supports it.

Sources/SwAuth/SwAuth Documentation.docc/Choosing which Authorization Flow to Use and When.md

Lines changed: 0 additions & 23 deletions
This file was deleted.

Sources/SwAuth/SwAuth Documentation.docc/DeviceAuthorizationFlow.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Getting Started
44

5-
To use the Device Authorization Grant Flow, first create an instance of Keychain and then create an instance of DeviceAuthorizationFlow by filling in the information of the WebAPI you wish to utilize. Google's TV API will be used as an example.
5+
To use the Device Authorization Grant Flow, first create an instance of Keychain and then create an instance of DeviceAuthorizationFlow by filling in the information of the Web API you wish to utilize. Google's TV authentication will be used as an example.
66

77
```swift
88
let keychain = Keychain(service: "com.your.bundleID",

0 commit comments

Comments
 (0)