Skip to content

Commit

Permalink
Adjust formatting and update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
fpseverino committed Nov 22, 2024
1 parent 0d08b17 commit 7a59e31
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 25 deletions.
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,3 @@
<br>

Imperial is a Federated Login service, allowing you to easily integrate your Vapor applications with OAuth providers to handle your apps authentication.

## Attribution
Author(s): @calebkleveter, @rafiki270
6 changes: 4 additions & 2 deletions Sources/Imperial/Services/DeviantArt/DeviantArtRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ public class DeviantArtRouter: FederatedServiceRouter {
} else {
scope = ""
}
return "https://www.deviantart.com/oauth2/authorize?" + "client_id=\(self.tokens.clientID)&"
+ "redirect_uri=\(self.callbackURL)&\(scope)" + "response_type=code"
return "https://www.deviantart.com/oauth2/authorize?"
+ "client_id=\(self.tokens.clientID)&"
+ "redirect_uri=\(self.callbackURL)&\(scope)"
+ "response_type=code"
}

public func fetchToken(from request: Request) throws -> Future<String> {
Expand Down
5 changes: 1 addition & 4 deletions Sources/ImperialCore/Helpers/Request+Imperial.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ extension Request {
throw ServiceError.noServiceEndpoint(model.serviceKey)
}

let token =
try service.tokenPrefix
+ req
.accessToken()
let token = try service.tokenPrefix + req.accessToken()

let response = try await req.client.get(URI(string: url), headers: ["Authorization": token])
let instance = try await model.init(from: response)
Expand Down
34 changes: 22 additions & 12 deletions Sources/ImperialCore/Services/FederatedService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,32 @@ import Vapor
/// Usage:
///
/// ```swift
/// import HTTP
/// import ImperialCore
/// import Vapor
///
/// public class Service: FederatedService {
/// public var tokens: FederatedServiceTokens
/// public var router: FederatedServiceRouter
/// public var tokens: any FederatedServiceTokens
/// public var router: any FederatedServiceRouter
///
/// @discardableResult
/// public required init(authenticate: String, callback: String, scope: [String] = [], completion: @escaping (String) -> (ResponseRepresentable)) throws {
/// self.router = try ServiceRouter(callback: callback, completion: completion)
/// public required init(
/// routes: some RoutesBuilder,
/// authenticate: String,
/// authenticateCallback: (@Sendable (Request) async throws -> Void)?,
/// callback: String,
/// scope: [String] = [],
/// completion: @escaping @Sendable (Request, String) async throws -> some AsyncResponseEncodable
/// ) throws {
/// self.router = try ServiceRouter(callback: callback, scope: scope, completion: completion)
/// self.tokens = self.router.tokens
///
/// self.router.scope = scope
/// try self.router.configureRoutes(withAuthURL: authenticate, authenticateCallback: authenticateCallback, on: router)
/// try self.router.configureRoutes(withAuthURL: authenticate, authenticateCallback: authenticateCallback, on: routes)
///
/// Service.register(.service)
/// OAuthService.services[OAuthService.service.name] = .service
/// }
/// }
/// ```
public protocol FederatedService {

/// The service's token model for getting the client ID and secret.
var tokens: any FederatedServiceTokens { get }

Expand All @@ -41,7 +47,11 @@ public protocol FederatedService {
/// - completion: The completion handler that will fire at the end of the callback route. The access token is passed into the callback and the response that is returned will be returned from the callback route. This will usually be a redirect back to the app.
/// - Throws: Any errors that occur in the implementation.
init(
routes: some RoutesBuilder, authenticate: String, authenticateCallback: (@Sendable (Request) async throws -> Void)?,
callback: String, scope: [String], completion: @escaping @Sendable (Request, String) async throws -> some AsyncResponseEncodable)
throws
routes: some RoutesBuilder,
authenticate: String,
authenticateCallback: (@Sendable (Request) async throws -> Void)?,
callback: String,
scope: [String],
completion: @escaping @Sendable (Request, String) async throws -> some AsyncResponseEncodable
) throws
}
7 changes: 5 additions & 2 deletions Sources/ImperialKeycloak/KeycloakRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ final public class KeycloakRouter: FederatedServiceRouter {
}

public func authURL(_ request: Request) throws -> String {
return "\(keycloakTokens.authURL)/auth?" + "client_id=\(self.tokens.clientID)&" + "redirect_uri=\(self.callbackURL)&"
+ "scope=\(scope.joined(separator: "%20"))&" + "response_type=code"
return "\(keycloakTokens.authURL)/auth?"
+ "client_id=\(self.tokens.clientID)&"
+ "redirect_uri=\(self.callbackURL)&"
+ "scope=\(scope.joined(separator: "%20"))&"
+ "response_type=code"
}

public func callbackBody(with code: String) -> any AsyncResponseEncodable {
Expand Down
8 changes: 6 additions & 2 deletions Sources/ImperialShopify/ShopifyRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ final public class ShopifyRouter: FederatedServiceRouter {
public let callbackURL: String
// `accessTokenURL` used to be set inside `authURL` and read by `fetchToken`
// now `fetchToken` creates the `accessTokenURL` itself from the shop domain in the request
// but the property is still required by the protocol, so it's set to an empty string
public let accessTokenURL: String = ""
public let service: OAuthService = .shopify

Expand All @@ -25,8 +26,11 @@ final public class ShopifyRouter: FederatedServiceRouter {
let nonce = String(UUID().uuidString.prefix(6))
try request.session.setNonce(nonce)

return "https://\(shop)/admin/oauth/authorize?" + "client_id=\(tokens.clientID)&" + "scope=\(scope.joined(separator: ","))&"
+ "redirect_uri=\(callbackURL)&" + "state=\(nonce)"
return "https://\(shop)/admin/oauth/authorize?"
+ "client_id=\(tokens.clientID)&"
+ "scope=\(scope.joined(separator: ","))&"
+ "redirect_uri=\(callbackURL)&"
+ "state=\(nonce)"
}

public func callbackBody(with code: String) -> any AsyncResponseEncodable {
Expand Down

0 comments on commit 7a59e31

Please sign in to comment.