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
2 changes: 1 addition & 1 deletion Sources/OAuthKit/Extensions/URL+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extension URL {
absoluteString.sha256
}

/// Returns the SHA-256 Digest for this URL.
/// Returns the SHA-512 Digest for this URL.
var sha512: SHA512.Digest {
absoluteString.sha512
}
Expand Down
1 change: 0 additions & 1 deletion Sources/OAuthKit/Keychain/Keychain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class Keychain: @unchecked Sendable {
guard status == noErr else { return [] }

var results = [String]()

if let items = result as? [[String: Any]] {
for item in items {
if let key = item[kSecAttrAccount as String] as? String {
Expand Down
2 changes: 1 addition & 1 deletion Sources/OAuthKit/OAuth+DeviceCode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation

extension OAuth {

/// A codable type that holds device code information.
/// A codable type returned from a server that holds device code information.
/// - SeeAlso:
/// [Requesting a Device Code](https://www.oauth.com/playground/device-code.html)
public struct DeviceCode: Codable, Equatable, Sendable {
Expand Down
12 changes: 5 additions & 7 deletions Sources/OAuthKit/OAuth+GrantType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,30 @@ import Foundation
extension OAuth {

/// Provides an enum representation for the OAuth 2.0 Grant Types.
///
/// See: https://oauth.net/2/grant-types/
public enum GrantType: Equatable, Sendable {

/// The OAuth 2.0 authorization code workflow.
/// See: https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1
/// See RFC 6749 Standard [OAuth 2.0 Authorization Code Grant Type](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1)
/// - Parameters:
/// - String: the state verification string used to prevent CSRF attacks
case authorizationCode(String)

/// The OAuth 2.0 client credentials grant.
/// See: https://datatracker.ietf.org/doc/html/rfc6749#section-4.4
/// See RFC 6749 Standard [OAuth 2.0 Client Credentials Code Grant Type](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4)
case clientCredentials

/// The OAuth 2.0 device authorization grant.
/// See: https://datatracker.ietf.org/doc/html/rfc8628#section-3.4
/// See RFC 6749 Standard [OAuth 2.0 Device Code Grant Type](https://datatracker.ietf.org/doc/html/rfc8628#section-3.4)
case deviceCode

/// The OAuth 2.0 Proof Key for Code Exchange is an extension to the Authorization Code
/// flow to prevent CSRF and authorization code injection attacks.
/// flow to prevent CSRF and authorization code injection attacks. See RFC 7636 Standard [OAuth 2.0 Proof Key for Code Exchange](https://datatracker.ietf.org/doc/html/rfc7636)
/// - Parameters:
/// - PKCE: the PKCE data
case pkce(PKCE)

/// The OAuth 2.0 Refresh Token grant type is used by clients to exchange a refresh token for an access token when the access token has expired.
/// See: https://datatracker.ietf.org/doc/html/rfc6749#section-1.5
/// See RFC 6749 Standard [OAuth 2.0 Refresh Token](https://datatracker.ietf.org/doc/html/rfc6749#section-1.5)
case refreshToken

/// The raw string value for a grant type.
Expand Down
21 changes: 10 additions & 11 deletions Sources/OAuthKit/OAuth+PKCE.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,22 @@ private let defaultCodeChallengeMethod = "S256"

extension OAuth {

/// Provides a structure for OAuth 2.0 Authorization Code Flow with Proof Key for Code Exchange (PKCE)
/// Provides a structure for OAuth 2.0 Authorization Code Flow with Proof Key for Code Exchange (PKCE).
public struct PKCE: Equatable, Sendable {

/// A cryptographically random string using the characters A-Z, a-z, 0-9, and the punctuation characters -
/// ._~ (hyphen, period, underscore, and tilde), between 43 and 128 characters long.
/// See: https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
let codeVerifier: String
/// A cryptographically random string between 43 and 128 characters long.
/// See RFC 7636 Standard [PKCE Code Verifier](https://datatracker.ietf.org/doc/html/rfc7636#section-4.1).
public let codeVerifier: String

/// A transformation of the codeVerifier that is SHA-256 hashed and Base 64 URL encoded.
/// See: https://datatracker.ietf.org/doc/html/rfc7636#section-4.2
let codeChallenge: String
/// A code challenge derived from the codeVerifier that is a Base 64 URL encoded string from it's SHA-256 digest.
/// See RFC 7636 Standard [PKCE Code Challenge](https://datatracker.ietf.org/doc/html/rfc7636#section-4.2).
public let codeChallenge: String

/// The PKCE state code.
let state: String
public let state: String

/// Returns the code challenge method.
var codeChallengeMethod: String {
/// Returns the code challenge method. Currently only supports [SHA-256 hash](https://en.wikipedia.org/wiki/SHA-2).
public var codeChallengeMethod: String {
defaultCodeChallengeMethod
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/OAuthKit/OAuth+Provider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation

extension OAuth {

/// Provides configuration data for an OAuth service provider.
/// Provides configuration data for an OAuth 2.0 service provider.
public struct Provider: Codable, Identifiable, Hashable, Sendable {

/// The provider unique id.
Expand Down
30 changes: 30 additions & 0 deletions Sources/OAuthKit/OAuthKit.docc/Extensions/GrantType.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ``OAuthKit/OAuth/GrantType``

@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
A GrantType is used to define how an application obtains an access token from an OAuth 2.0 server. OAuthKit supports all major OAuth 2.0 grant types:
- [Authorization Code](``authorizationCode(_:)``)
- [Client Credentials](``clientCredentials``)
- [Device Code](``deviceCode``)
- [Proof Key for Code Exchange (PKCE)](``pkce(_:)``)
- [Refresh Token](``refreshToken``)


> Important: For apps that don't have access to a web browser (like tvOS or watchOS), you'll need to start
an ``OAuth/authorize(provider:grantType:)`` flow with the ``deviceCode`` grant Type. See <doc:GettingStarted> for more details.

> Tip: The [OAuth 2.0 Playground](https://www.oauth.com/playground/index.html) will help you understand the OAuth authorization flows and show each step of the process of obtaining an access token.

## Topics

### Associated Values

- ``OAuth/PKCE``
- ``OAuth/DeviceCode``
8 changes: 8 additions & 0 deletions Sources/OAuthKit/OAuthKit.docc/Extensions/OAuth.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# ``OAuthKit/OAuth``
@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")
}

## Topics

Expand All @@ -10,6 +17,7 @@
### Starting an authorization flow

- ``authorize(provider:grantType:)``
- ``OAuth/GrantType``

### OAuth State Tracking

Expand Down
32 changes: 32 additions & 0 deletions Sources/OAuthKit/OAuthKit.docc/Extensions/Provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# ``OAuthKit/OAuth/Provider``

@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
The Provider holds the configuration data that is used for communicating with an OAuth 2.0 server. 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 ``SwiftUICore/EnvironmentValues/oauth`` property wrapper. You can find an example `oauth.json` file [here](https://github.com/codefiesta/OAuthKit/blob/main/Tests/OAuthKitTests/Resources/oauth.json).
```json
[
{
"id": "GitHub",
"authorizationURL": "https://github.com/login/oauth/authorize",
"accessTokenURL": "https://github.com/login/oauth/access_token",
"deviceCodeURL": "https://github.com/login/device/code",
"clientID": "CLIENT_ID",
"clientSecret": "CLIENT_SECRET",
"redirectURI": "oauthkit://callback",
"scope": [
"user",
"repo",
"openid"
],
"debug": true
}
]
```
> Warning: It's highly recommended that developers only use `oauth.json` files during development and don't include them in publicly distributed applications. It is possible for someone to [inspect and reverse engineer](https://www.nowsecure.com/blog/2021/09/08/basics-of-reverse-engineering-ios-mobile-apps/) the contents of your app and look at any files inside your app bundle which means you could potentially expose any confidential values contained in this file. It's recommended to build OAuth Providers Programmatically via your CI Build Pipeline. Most continuous integration and delivery platforms have the ability to generate source code during build workflows that can get compiled into Swift byte code. It's should be feasible to write a step in the CI pipeline that generates a .swift file that provides access to a list of OAuth.Provider objects that have their confidential values set from the secure CI platform secret keys. This swift code can then compiled into the application as byte code. In practical terms, the security and obfuscation inherent in compiled languages make extracting confidential values difficult (but not impossible).
2 changes: 2 additions & 0 deletions Sources/OAuthKit/OAuthKit.docc/OAuthKit.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ This has the advantage of avoiding direct coupling with an authorization flow, e
- <doc:GettingStarted>
- <doc:SampleCode>
- ``OAuth``
- ``OAuth/Provider``
- ``OAuth/GrantType``

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