Skip to content

Commit

Permalink
Convert docs to DocC (#112)
Browse files Browse the repository at this point in the history
* Add DocC catalog and update all services docs
  • Loading branch information
fpseverino authored Dec 17, 2024
1 parent b2c85c9 commit ac84c96
Show file tree
Hide file tree
Showing 136 changed files with 419 additions and 20,230 deletions.
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ let package = Package(
"ImperialMicrosoft",
"ImperialMixcloud",
"ImperialShopify",
]),
]
),
],
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
Expand Down
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,79 @@
</div>
<br>

🔐 Federated Authentication with OAuth providers for Vapor.

### Installation

Use the SPM string to easily include the dependendency in your `Package.swift` file

```swift
.package(url: "https://github.com/vapor-community/Imperial.git", from: "2.0.0-beta.1")
```

and then add the desired provider to your target's dependencies:

```swift
.product(name: "ImperialGitHub", package: "imperial")
```

## Overview

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

## Getting Started

### Sessions Middleware

Imperial relies on the [sessions middleware](https://docs.vapor.codes/4.0/sessions/#configuration) to save state and access tokens. In **configure.swift**, or as a route group for specific routes, add the sessions middleware. For example, to add it globally:

```swift
app.middleware.use(app.sessions.middleware)
```

### Route Registration

Imperial uses environment variables to access the client ID and secret to authenticate with the provider. See the provider specific docs for details on what they should be.

You need to register the OAuth service with your route. For example, to register a GitHub integration add the following:

```swift
try routes.oAuth(from: GitHub.self, authenticate: "github", callback: "gh-auth-complete") { req, token in
print(token)
return req.redirect(to: "/")
}
```

This registers a route to `/github`. When you visit that route, Imperial will trigger the OAuth flow using the `GitHub` service. The callback path is the one registered with the OAuth provider when you create your application. The completion handler is fired when the callback route is called by the OAuth provider. The access token is passed in and a response is returned.

If you just want to redirect, without doing anything else in the callback, you can use the helper ``RoutesBuilder/oAuth(from:authenticate:authenticateCallback:callback:scope:redirect:)`` method that takes in a redirect string:

```swift
try router.oAuth(from: GitHub.self, authenticate: "github", callback: "gh-auth-complete", redirect: "/")
```

### Access Tokens and Middleware

If you ever want to get the `access_token` in a route, you can use a helper method for the `Request` type that comes with Imperial:

```swift
let token = try request.accessToken
```

Now that you are authenticating the user, you will want to protect certain routes to make sure the user is authenticated. You can do this by adding the ``ImperialMiddleware`` to a router group (or maybe your middleware config):

```swift
let protected = routes.grouped(ImperialMiddleware())
```

Then, add your protected routes to the `protected` group:

```swift
protected.get("me", use: me)
```

The ``ImperialMiddleware`` by default passes the errors it finds onto `ErrorMiddleware` where they are caught, but you can initialize it with a redirect path to go to if the user is not authenticated:

```swift
let protected = routes.grouped(ImperialMiddleware(redirect: "/"))
```
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
# Federated Login with Auth0
# ``ImperialAuth0``

## Auth0 Setup
Federated Authentication with Auth0 for Vapor.

We need to start by creating a regular web application so Auth0 can identify us. Go to the Applications menu from the side-bar on your Auth0 Dashboard.
## Overview

Select '+ Create Application'. Provide a name for your app and select 'Regular Web Applications'. Then select 'Create'.
### Auth0 Setup

![Create Application Screenshot](Applications-Marked.png)
We need to start by creating a regular web application so Auth0 can identify us.
Go to the Applications menu from the side-bar on your Auth0 Dashboard.

Go to the 'Settings' tab for your application to find your Domain, Client ID, and Client Secret.
Select `+ Create Application`.
Provide a name for your app and select `Regular Web Applications`.
Then select `Create`.

![Setting-1](SamplePortal-Settings-1.png)
![Create Application Screenshot](Applications-Marked)

You'll want to configure this is a "Regular Web Application" using "POST" for the Token Endpoint Authentication Method.
Go to the `Settings` tab for your application to find your Domain, Client ID, and Client Secret.

![Setting-1](SamplePortal-Settings-1)

![Settings-2](SamplePortal-Settings-2.png)
You'll want to configure this is a "Regular Web Application" using "POST" for the Token Endpoint Authentication Method.

![Settings-2](SamplePortal-Settings-2)

Be sure to configure the proper settings for:
- Allowed Callback URLs
Expand All @@ -34,14 +40,13 @@ If testing on your local system, you can start with the following settings:
- Allowed Logout URLs:
- http://localhost:8080/, https://localhost/, https://127.0.0.1/

![Settings-3](SamplePortal-Settings-3.png)

![Settings-4](SamplePortal-Settings-4.png)
![Settings-3](SamplePortal-Settings-3)

![Settings-4](SamplePortal-Settings-4)

This provides you with an OAuth Client ID and secret you can provide to Imperial.

## Imperial Integration
### Imperial Integration

You can use Auth0 with the `ImperialAuth0` package. This expects three environment variables:

Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
3 changes: 2 additions & 1 deletion Sources/ImperialCore/FederatedService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Vapor

/// Represents a connection to an OAuth provider to get an access token for authenticating a user.
///
/// Usage:
/// Here is an example of the implementation of a federated service:
///
/// ```swift
/// import ImperialCore
Expand All @@ -27,6 +27,7 @@ public protocol FederatedService: Sendable {
/// Creates a service for getting an access token from an OAuth provider.
///
/// - Parameters:
/// - routes: The routes builder to configure the routes for the service.
/// - authenticate: The path for the route that will redirect the user to the OAuth provider for authentication.
/// - authenticateCallback: Execute custom code within the authenticate closure before redirection.
/// - callback: The path (or URI) for the route that the provider will call when the user authenticates.
Expand Down
62 changes: 62 additions & 0 deletions Sources/ImperialCore/ImperialCore.docc/GettingStarted.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Getting Started with Imperial

Federated Authentication with OAuth providers for Vapor.

## Overview

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

### Sessions Middleware

Imperial relies on the [sessions middleware](https://docs.vapor.codes/4.0/sessions/#configuration) to save state and access tokens. In **configure.swift**, or as a route group for specific routes, add the sessions middleware. For example, to add it globally:

```swift
app.middleware.use(app.sessions.middleware)
```

### Route Registration

Imperial uses environment variables to access the client ID and secret to authenticate with the provider. See the provider specific docs for details on what they should be.

You need to register the OAuth service with your route. For example, to register a GitHub integration add the following:

```swift
try routes.oAuth(from: GitHub.self, authenticate: "github", callback: "gh-auth-complete") { req, token in
print(token)
return req.redirect(to: "/")
}
```

This registers a route to `/github`. When you visit that route, Imperial will trigger the OAuth flow using the `GitHub` service. The callback path is the one registered with the OAuth provider when you create your application. The completion handler is fired when the callback route is called by the OAuth provider. The access token is passed in and a response is returned.

If you just want to redirect, without doing anything else in the callback, you can use the helper `oAuth(from:authenticate:authenticateCallback:callback:scope:redirect:)` method that takes in a redirect string:

```swift
try router.oAuth(from: GitHub.self, authenticate: "github", callback: "gh-auth-complete", redirect: "/")
```

### Access Tokens and Middleware

If you ever want to get the `access_token` in a route, you can use a helper method for the `Request` type that comes with Imperial:

```swift
let token = try request.accessToken
```

Now that you are authenticating the user, you will want to protect certain routes to make sure the user is authenticated. You can do this by adding the ``ImperialMiddleware`` to a router group (or maybe your middleware config):

```swift
let protected = routes.grouped(ImperialMiddleware())
```

Then, add your protected routes to the `protected` group:

```swift
protected.get("me", use: me)
```

The ``ImperialMiddleware`` by default passes the errors it finds onto `ErrorMiddleware` where they are caught, but you can initialize it with a redirect path to go to if the user is not authenticated:

```swift
let protected = routes.grouped(ImperialMiddleware(redirect: "/"))
```
17 changes: 17 additions & 0 deletions Sources/ImperialCore/ImperialCore.docc/ImperialCore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# ``ImperialCore``

Federated Authentication with OAuth providers for Vapor.

## Overview

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

The ImperialCore framework provides a set of tools shared by all Imperial provider frameworks.

## Topics

### Essentials

- <doc:GettingStarted>
- ``ImperialCore/Vapor/RoutesBuilder/oAuth(from:authenticate:authenticateCallback:callback:scope:completion:)``
- ``ImperialCore/Vapor/RoutesBuilder/oAuth(from:authenticate:authenticateCallback:callback:scope:redirect:)``
9 changes: 6 additions & 3 deletions Sources/ImperialCore/Middleware/ImperialMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ public struct ImperialMiddleware: AsyncMiddleware {
/// The path to redirect the user to if they are not authenticated.
let redirectPath: String?

/// Creates an instance of `ImperialMiddleware` with the option of a redirect path.
/// Creates an instance of ``ImperialMiddleware`` with the option of a redirect path.
///
/// - Parameter redirect: The path to redirect a user to if they do not have an access token.
public init(redirect: String? = nil) {
self.redirectPath = redirect
}

/// Checks that the request contains an access token. If it does, let the request through.
/// Checks that the request contains an access token.
///
/// If it does, let the request through.
/// If not, redirect the user to the `redirectPath`.
/// If the `redirectPath` is `nil`, then throw the error from getting the access token (Abort.unauthorized).
///
/// - Throws: If the `redirectPath` is `nil`, then throw the error from getting the access token (`Abort.unauthorized`).
public func respond(to request: Request, chainingTo next: any AsyncResponder) async throws -> Response {
do {
_ = try request.accessToken
Expand Down
17 changes: 6 additions & 11 deletions Sources/ImperialCore/RoutesBuilder+oAuth.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import Vapor

extension RoutesBuilder {
/// Registers an OAuth provider's router with
/// the parent route.
/// Registers an OAuth provider's router with the parent route.
///
/// - Parameters:
/// - provider: The provider who's router will be used.
/// - authUrl: The path to navigate to authenticate.
/// - authenticateCallback: Execute custom code within the authenticate closure before redirection.
/// - callback: The path or URL that the provider with
/// redirect to when authentication completes.
/// - callback: The path or URL that the provider with redirect to when authentication completes.
/// - scope: The scopes to get access to on authentication.
/// - completion: A callback with the current request and fetched
/// access token that is called when auth completes.
/// - completion: A callback with the current request and fetched access token that is called when auth completes.
public func oAuth<OAuthProvider>(
from provider: OAuthProvider.Type,
authenticate authUrl: String,
Expand All @@ -31,17 +28,15 @@ extension RoutesBuilder {
)
}

/// Registers an OAuth provider's router with
/// the parent route and a redirection callback.
/// Registers an OAuth provider's router with the parent route and a redirection callback.
///
/// - Parameters:
/// - provider: The provider who's router will be used.
/// - authUrl: The path to navigate to authenticate.
/// - authenticateCallback: Execute custom code within the authenticate closure before redirection.
/// - callback: The path or URL that the provider with
/// redirect to when authentication completes.
/// - callback: The path or URL that the provider with redirect to when authentication completes.
/// - scope: The scopes to get access to on authentication.
/// - redirect: The path/URL to redirect to when auth completes.
/// - redirectURL: The path/URL to redirect to when auth completes.
public func oAuth<OAuthProvider>(
from provider: OAuthProvider.Type,
authenticate authUrl: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# Federated Login with DeviantArt
# ``ImperialDeviantArt``

## DeviantArt Setup
Federated Authentication with DeviantArt for Vapor.

Start by going to the [DeviantArt developers page](https://www.deviantart.com/developers/). Click the 'Register your Application' button.
## Overview

![Create the app](create-application.png)
### DeviantArt Setup

Start by going to the [DeviantArt developers page](https://www.deviantart.com/developers/).
Click the `Register your Application` button.

![Create the app](create-application)

Fill in the app information, particularly the OAuth2 Redirect URI Whitelist:

![Redirect URI](callback-url.png)
![Redirect URI](callback-url)

This provides you with an OAuth Client ID and secret you can provide to Imperial.

## Imperial Integration
### Imperial Integration

You can use DeviantArt with the `ImperialDeviantArt` package. This expects two environment variables:

Expand Down
File renamed without changes
File renamed without changes
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
# Federated Login with Discord
# ``ImperialDiscord``

## Discord Setup
Federated Authentication with Discord for Vapor.

Start by going to the [Discord Developer Portal](https://discord.com/developers/applications), and creating an "New Application".
## Overview

### Discord Setup

Start by going to the [Discord Developer Portal](https://discord.com/developers/applications), and creating a "New Application".
In the "OAuth2" tab click "Add Redirect" and fill in your callback URL.

## Imperial Integration
### Imperial Integration

You can use Discord with the `ImperialDiscord` package. This expects two environment variables:

* `DISCORD_CLIENT_ID`
* `DISCORD_CLIENT_SECRET`

Additionally you must set `DiscordRouter.callbackURL` to an valid Redirect URL you added in the Developer Portal.
Additionally you must set `callback` to an valid Redirect URL you added in the Developer Portal.

You can then register the OAuth provider like normal.
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# Federated Login with Dropbox
# ``ImperialDropbox``

## Dropbox Setup
Federated Authentication with Dropbox for Vapor.

Start by going to the [Dropbox App console page](https://dropbox.com/developers/apps/). Click the 'Create App' button. Choose your API, access type, and name, then click 'Create App':
## Overview

![Create the app](create-application.png)
### Dropbox Setup

Start by going to the [Dropbox App console page](https://dropbox.com/developers/apps/).
Click the `Create App` button. Choose your API, access type, and name, then click `Create App`:

![Create the app](create-application)

Fill in the rest of the app information, particularly the Redirect URIs:

![Redirect URI](callback-url.png)
![Redirect URI](callback-url)

This provides you with an OAuth Client ID and secret you can provide to Imperial.

## Imperial Integration
### Imperial Integration

You can use Dropbox with the `ImperialDropbox` package. This expects two environment variables:

Expand Down
File renamed without changes
File renamed without changes
Loading

0 comments on commit ac84c96

Please sign in to comment.