authentik-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.md +21 -0
- data/README.md +294 -0
- data/Rakefile +10 -0
- data/lib/authentik/api_proxy.rb +40 -0
- data/lib/authentik/client/configuration.rb +38 -0
- data/lib/authentik/client/railtie.rb +34 -0
- data/lib/authentik/client/version.rb +7 -0
- data/lib/authentik/client.rb +159 -0
- data/mise.toml +29 -0
- metadata +161 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 24871367b4b0088be76770175ded67c9b75cdb9ab2caae7998a90ccb08d25fcd
|
|
4
|
+
data.tar.gz: 8cd0c9eb33a1190635f70ac09ee4a3beb69a2a73dd4bee48a8c41ef2bd315f66
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 257b35255cfea42bca4769f907e73734ec6e8e0795371fe7d4c3fc90efae70100c4c4fc3e99404e38edd2d456586a71770d0202838cb97fb46d6d9f188fbe6fb
|
|
7
|
+
data.tar.gz: 9aa0e218a8ee23ae0aaefb8ac8a5c036556ee8523bb40b7d787bd24f3d5ac8bbf6ba241efd85337413ffef906965ac57c313b35b3299c4407e9e52566d161ced
|
data/CHANGELOG.md
ADDED
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
This project follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.):
|
|
4
|
+
|
|
5
|
+
* Participants will be tolerant of opposing views.
|
|
6
|
+
* Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
|
|
7
|
+
* When interpreting the words and actions of others, participants should always assume good intentions.
|
|
8
|
+
* Behavior which can be reasonably considered harassment will not be tolerated.
|
|
9
|
+
|
|
10
|
+
If you have any concerns about behavior within this project, please contact us at ["david.uhlig@gmail.com"](mailto:"david.uhlig@gmail.com").
|
data/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 David Uhlig
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# 🔓 authentik API Client
|
|
2
|
+
|
|
3
|
+
[][gem]
|
|
4
|
+
[][license]
|
|
5
|
+
[][tests]
|
|
6
|
+
|
|
7
|
+
An idiomatic Ruby interface for the [authentik] API; the open-source Identity Provider (IdP) and Single Sign On (SSO) platform.
|
|
8
|
+
|
|
9
|
+
This library lets you manage configuration objects in authentik - such as users, groups, and more - through a clean Ruby interface. It is *not* intended for handling SSO within your own application.
|
|
10
|
+
|
|
11
|
+
Built as a developer-friendly wrapper around the auto-generated [authentik-api] gem (via OpenAPI Generator), it simplifies common tasks and abstracts away much of the low-level complexity of the underlying client.
|
|
12
|
+
|
|
13
|
+
> [!TIP]
|
|
14
|
+
> For guidance on handling authentication, see [Authentication with authentik in Ruby](#authentication-with-authentik-in-ruby).
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
Add the following line to your application's Gemfile:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
gem "authentik-client"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Then install the dependencies with `bundle install`. Alternatively, you can add the gem directly from the commandline: `bundle add "authentik-client"`.
|
|
25
|
+
|
|
26
|
+
This installs the latest release of the baseline [authentik-api] client, which tracks the most recent authentik release.
|
|
27
|
+
|
|
28
|
+
To ensure compatibility with a specific authentik version, explicitly require a matching `authentik-api` version:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
# Use the latest `2026.2.x` series release (excluding release candidates).
|
|
32
|
+
gem "authentik-api" "~> 2026.2.0"
|
|
33
|
+
gem "authentik-client"
|
|
34
|
+
# Pin to an exact patch version.
|
|
35
|
+
gem "authentik-api" "2026.2.1"
|
|
36
|
+
gem "authentik-client"
|
|
37
|
+
# Test a release candidate.
|
|
38
|
+
gem "authentik-api" "2026.5.0-rc1"
|
|
39
|
+
gem "authentik-client"
|
|
40
|
+
# Use the latest unreleased code from GitHub.
|
|
41
|
+
# Tracks authentik's main branch and updates daily when the OpenAPI schema changes.
|
|
42
|
+
gem "authentik-api", github: "david-uhlig/authentik-api"
|
|
43
|
+
gem "authentik-client"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
### Configuration
|
|
49
|
+
|
|
50
|
+
This gem offers three ways to initialize the authentik API client:
|
|
51
|
+
|
|
52
|
+
* [At startup](#configuring-at-startup), with an initializer
|
|
53
|
+
* [A Rails configuration file](#rails-integration), e.g. `config/application.rb`
|
|
54
|
+
* [At runtime](#creating-a-client)
|
|
55
|
+
|
|
56
|
+
You can freely mix startup and runtime initialization; i.e., initialize the host in a Rails configuration file and provide the token at runtime.
|
|
57
|
+
|
|
58
|
+
#### Configuring at startup
|
|
59
|
+
|
|
60
|
+
You can configure `Authentik::Client` once globally. For example, at application startup (e.g., in a Rails initializer), and then create client instances without repeating connection details:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
# config/initializers/authentik.rb
|
|
64
|
+
Authentik::Client.configure do |config|
|
|
65
|
+
config.host = "authentik.example.com"
|
|
66
|
+
config.token = "your-api-token"
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
With a global configuration in place, clients can be created without arguments:
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
client = Authentik::Client.new
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
But you can also overwrite any globally configured attribute:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
client = Authentik::Client.new(token: "your-runtime-api-token")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> [!NOTE]
|
|
83
|
+
> Global configuration is fully optional.
|
|
84
|
+
|
|
85
|
+
#### Rails integration
|
|
86
|
+
|
|
87
|
+
Alternatively, when using the gem in a Rails application, it automatically loads a [Railtie](lib/authentik/client/railtie.rb) that exposes `config.authentik_client` as a standard Rails configuration accessor.
|
|
88
|
+
|
|
89
|
+
`config.authentik_client` is the same configuration class instance as `Authentik::Client.configuration`, so both styles are always in sync.
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
# config/application.rb (or any environment file)
|
|
93
|
+
|
|
94
|
+
# ...
|
|
95
|
+
module YourApplication
|
|
96
|
+
class Application < Rails::Application
|
|
97
|
+
# ...
|
|
98
|
+
config.authentik_client.host = "authentik.example.com"
|
|
99
|
+
config.authentik_client.token = ENV["AUTHENTIK_TOKEN"]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
You can also use environment-specific files:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
# config/environments/production.rb
|
|
108
|
+
|
|
109
|
+
# ...
|
|
110
|
+
module YourApplication
|
|
111
|
+
class Application < Rails::Application
|
|
112
|
+
# ...
|
|
113
|
+
config.authentik_client.verify_ssl = true
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### Creating a client
|
|
119
|
+
|
|
120
|
+
Finally, you can configure client instances at runtime.
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
client = Authentik::Client.new(
|
|
124
|
+
host: "authentik.example.com",
|
|
125
|
+
token: "your-api-token"
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Additional configuration options are forwarded to the underlying, auto-generated OpenAPI client:
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
client = Authentik::Client.new(
|
|
133
|
+
host: "authentik.example.com",
|
|
134
|
+
token: "your-api-token",
|
|
135
|
+
scheme: "https", # default
|
|
136
|
+
verify_ssl: false, # disable SSL verification (e.g. for development)
|
|
137
|
+
timeout: 60 # request timeout in seconds
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
See [`Authentik::Api::Configuration`](https://github.com/david-uhlig/authentik-api/blob/main/lib/authentik/api/configuration.rb) for a list of all available configuration options.
|
|
142
|
+
|
|
143
|
+
### Calling API endpoints
|
|
144
|
+
|
|
145
|
+
The client exposes each API group as a method. Calling an API group method returns a proxy object that forwards calls to the corresponding auto-generated API class, with the redundant group prefix stripped for brevity.
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
# Core API – lists applications.
|
|
149
|
+
#
|
|
150
|
+
# Calls `Authentik::Api::CoreApi.core_applications_list`.
|
|
151
|
+
# Issues a `GET` request to the `/api/v3/core/applications/` endpoint,
|
|
152
|
+
# see: https://api.goauthentik.io/reference/core-applications-list/.
|
|
153
|
+
client.core.applications_list
|
|
154
|
+
|
|
155
|
+
# Admin API – retrieves the authentik version.
|
|
156
|
+
client.admin.version_retrieve
|
|
157
|
+
|
|
158
|
+
# OAuth2 API – lists access tokens.
|
|
159
|
+
client.oauth2.access_tokens_list
|
|
160
|
+
|
|
161
|
+
# Propertymappings API – lists all property mappings.
|
|
162
|
+
client.propertymappings.all_list
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The full list of API groups and their methods is available in the
|
|
166
|
+
[auto-generated README](https://github.com/david-uhlig/authentik-api/blob/main/README_API.md) and on [api.goauthentik.io](https://api.goauthentik.io/).
|
|
167
|
+
|
|
168
|
+
**Each API group is only initialized once when first requested.**
|
|
169
|
+
|
|
170
|
+
> [!TIP]
|
|
171
|
+
> If you're primarily using one API group, you can assign it to a variable and do:
|
|
172
|
+
> ```ruby
|
|
173
|
+
> propmap_api = client.propertymappings
|
|
174
|
+
> propmap_api.all_list
|
|
175
|
+
> ```
|
|
176
|
+
> instead of:
|
|
177
|
+
> ```ruby
|
|
178
|
+
> client.propertymappings.all_list
|
|
179
|
+
> ```
|
|
180
|
+
|
|
181
|
+
### Available API groups
|
|
182
|
+
|
|
183
|
+
The full API reference is available at [api.goauthentik.io](https://api.goauthentik.io/).
|
|
184
|
+
|
|
185
|
+
| Method | API class |
|
|
186
|
+
|---------------------------|-----------------------|
|
|
187
|
+
| `client.admin` | `AdminApi` |
|
|
188
|
+
| `client.authenticators` | `AuthenticatorsApi` |
|
|
189
|
+
| `client.core` | `CoreApi` |
|
|
190
|
+
| `client.crypto` | `CryptoApi` |
|
|
191
|
+
| `client.enterprise` | `EnterpriseApi` |
|
|
192
|
+
| `client.events` | `EventsApi` |
|
|
193
|
+
| `client.flows` | `FlowsApi` |
|
|
194
|
+
| `client.managed` | `ManagedApi` |
|
|
195
|
+
| `client.oauth2` | `Oauth2Api` |
|
|
196
|
+
| `client.outposts` | `OutpostsApi` |
|
|
197
|
+
| `client.policies` | `PoliciesApi` |
|
|
198
|
+
| `client.propertymappings` | `PropertymappingsApi` |
|
|
199
|
+
| `client.providers` | `ProvidersApi` |
|
|
200
|
+
| `client.rac` | `RacApi` |
|
|
201
|
+
| `client.rbac` | `RbacApi` |
|
|
202
|
+
| `client.root` | `RootApi` |
|
|
203
|
+
| `client.schema` | `SchemaApi` |
|
|
204
|
+
| `client.sources` | `SourcesApi` |
|
|
205
|
+
| `client.ssf` | `SsfApi` |
|
|
206
|
+
| `client.stages` | `StagesApi` |
|
|
207
|
+
| `client.tasks` | `TasksApi` |
|
|
208
|
+
| `client.tenants` | `TenantsApi` |
|
|
209
|
+
|
|
210
|
+
New API groups introduced by future authentik releases are automatically discovered without changes to `Authentik::Client` wrapper.
|
|
211
|
+
|
|
212
|
+
## Versioning
|
|
213
|
+
|
|
214
|
+
This library aims to adhere to [Semantic Versioning 2.0.0](http://semver.org/). Violations of this scheme should be reported as bugs.
|
|
215
|
+
|
|
216
|
+
## Development
|
|
217
|
+
|
|
218
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt.
|
|
219
|
+
|
|
220
|
+
To regenerate the underlying OpenAPI client run `bin/generate-api`.
|
|
221
|
+
|
|
222
|
+
## Contributing
|
|
223
|
+
|
|
224
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/david-uhlig/authentik-client. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/david-uhlig/authentik-client/blob/main/CODE_OF_CONDUCT.md).
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE.md).
|
|
229
|
+
|
|
230
|
+
## Code of Conduct
|
|
231
|
+
|
|
232
|
+
Everyone interacting in this project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [code of conduct](https://github.com/david-uhlig/authentik-client/blob/main/CODE_OF_CONDUCT.md).
|
|
233
|
+
|
|
234
|
+
## Attribution
|
|
235
|
+
|
|
236
|
+
* [authentik]: The open-source IdP and SSO platform. Providing flexible and scalable authentication.
|
|
237
|
+
|
|
238
|
+
> [!NOTE]
|
|
239
|
+
> This project is not affiliated with or endorsed by Authentik Security Inc.
|
|
240
|
+
|
|
241
|
+
## Appendix
|
|
242
|
+
|
|
243
|
+
### Authentication with authentik in Ruby
|
|
244
|
+
|
|
245
|
+
For integrating authentik authentication into your Ruby application, you can use [OmniAuth](https://github.com/omniauth/omniauth) with the [omniauth_oidc](https://github.com/msuliq/omniauth_oidc) gem, and an OAuth2/OIDC provider configured in authentik.
|
|
246
|
+
|
|
247
|
+
#### Quick Setup Guide for Rails
|
|
248
|
+
|
|
249
|
+
1\. Configure an OAuth2/OIDC provider under: `https://authentik.example.com/if/admin/#/core/providers`
|
|
250
|
+
|
|
251
|
+
2\. Add the gems to your Gemfile:
|
|
252
|
+
```ruby
|
|
253
|
+
gem 'omniauth'
|
|
254
|
+
gem 'omniauth_oidc'
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
3\. Configure OmniAuth
|
|
258
|
+
```ruby
|
|
259
|
+
# config/initializers/omniauth.rb
|
|
260
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
|
261
|
+
provider :oidc, {
|
|
262
|
+
name: :authentik,
|
|
263
|
+
client_options: {
|
|
264
|
+
identifier: ENV["CLIENT_ID"],
|
|
265
|
+
secret: ENV["CLIENT_SECRET"],
|
|
266
|
+
config_endpoint: "https://authentik.example.com/application/o/provider-slug/.well-known/openid-configuration"
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
end
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
4\. Add routes in `config/routes.rb`, e.g.:
|
|
273
|
+
```ruby
|
|
274
|
+
get "/auth/:provider/callback", to: "sessions#create"
|
|
275
|
+
get "/auth/failure", to: "sessions#failure"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
5\. Create a simple sessions controller:
|
|
279
|
+
```ruby
|
|
280
|
+
class SessionsController < ApplicationController
|
|
281
|
+
def create
|
|
282
|
+
user = User.from_omniauth(request.env['omniauth.auth'])
|
|
283
|
+
session[:user_id] = user.id
|
|
284
|
+
redirect_to root_path, notice: 'Signed in successfully!'
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
[authentik-api]: https://github.com/david-uhlig/authentik-api
|
|
290
|
+
[authentik]: https://github.com/goauthentik/authentik
|
|
291
|
+
[OpenAPI Generator]: https://openapi-generator.tech/
|
|
292
|
+
[gem]: https://rubygems.org/gems/authentik-client
|
|
293
|
+
[license]: https://github.com/david-uhlig/authentik-client/blob/main/LICENSE.md
|
|
294
|
+
[tests]: https://github.com/david-uhlig/authentik-client/actions/workflows/main.yml
|
data/Rakefile
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Authentik
|
|
4
|
+
# ApiProxy wraps an auto-generated OpenAPI API class and forwards method calls
|
|
5
|
+
# to it, stripping the redundant API group prefix from method names.
|
|
6
|
+
#
|
|
7
|
+
# For example, when accessed via +client.core+, the prefix +"core_"+ is
|
|
8
|
+
# stripped, so +client.core.applications_list+ calls
|
|
9
|
+
# +CoreApi#core_applications_list+.
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
class ApiProxy
|
|
13
|
+
# @param api_instance [Object] The underlying OpenAPI API class instance
|
|
14
|
+
# @param prefix [String] The method prefix to strip (e.g., +"core_"+)
|
|
15
|
+
def initialize(api_instance, prefix)
|
|
16
|
+
@api = api_instance
|
|
17
|
+
@prefix = prefix
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Forwards method calls to the underlying API instance.
|
|
21
|
+
# First tries with the prefix prepended (unless already prefixed), then without.
|
|
22
|
+
def method_missing(name, *args, **kwargs, &block)
|
|
23
|
+
prefixed = name.to_s.start_with?(@prefix) ? name : :"#{@prefix}#{name}"
|
|
24
|
+
if @api.respond_to?(prefixed)
|
|
25
|
+
@api.send(prefixed, *args, **kwargs, &block)
|
|
26
|
+
elsif @api.respond_to?(name)
|
|
27
|
+
@api.send(name, *args, **kwargs, &block)
|
|
28
|
+
else
|
|
29
|
+
super
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def respond_to_missing?(name, include_private = false)
|
|
34
|
+
prefixed = name.to_s.start_with?(@prefix) ? name : :"#{@prefix}#{name}"
|
|
35
|
+
@api.respond_to?(prefixed) ||
|
|
36
|
+
@api.respond_to?(name) ||
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Authentik
|
|
4
|
+
class Client
|
|
5
|
+
# Global configuration for {Authentik::Client}. Subclasses
|
|
6
|
+
# {Authentik::Api::Configuration} so all underlying API settings
|
|
7
|
+
# (e.g., +verify_ssl+, +timeout+, +debugging+) are available directly.
|
|
8
|
+
# Adds a +token+ accessor as a friendlier alias for +access_token+.
|
|
9
|
+
#
|
|
10
|
+
# Use {Authentik::Client.configure} to set configuration at startup.
|
|
11
|
+
#
|
|
12
|
+
# @example Configure at startup (e.g., in a Rails initializer)
|
|
13
|
+
# Authentik::Client.configure do |config|
|
|
14
|
+
# config.host = "authentik.example.com"
|
|
15
|
+
# config.token = "your-api-token"
|
|
16
|
+
# end
|
|
17
|
+
class Configuration < Authentik::Api::Configuration
|
|
18
|
+
def initialize
|
|
19
|
+
super
|
|
20
|
+
# Override parent defaults: host is intentionally nil until the user
|
|
21
|
+
# sets it, so Client can detect when it has not been configured.
|
|
22
|
+
@host = nil
|
|
23
|
+
@scheme = "https"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @return [String, nil] The API bearer token for authentication.
|
|
27
|
+
# Alias for +access_token+.
|
|
28
|
+
def token
|
|
29
|
+
access_token
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param value [String, nil]
|
|
33
|
+
def token=(value)
|
|
34
|
+
self.access_token = value
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/railtie"
|
|
4
|
+
require "authentik/client"
|
|
5
|
+
|
|
6
|
+
module Authentik
|
|
7
|
+
class Client
|
|
8
|
+
# Railtie integrates authentik-client with Ruby on Rails. It is
|
|
9
|
+
# automatically loaded when Rails is present, so no manual require is
|
|
10
|
+
# needed.
|
|
11
|
+
#
|
|
12
|
+
# Exposes +config.authentik_client+ so the client can be configured
|
|
13
|
+
# directly from Rails configuration files (e.g., +config/application.rb+
|
|
14
|
+
# or environment files). +config.authentik_client+ is the same
|
|
15
|
+
# {Authentik::Client::Configuration} instance returned by
|
|
16
|
+
# {Authentik::Client.configuration}, so both styles are always in sync.
|
|
17
|
+
#
|
|
18
|
+
# @example config/application.rb
|
|
19
|
+
# config.authentik_client.host = "authentik.example.com"
|
|
20
|
+
# config.authentik_client.token = ENV["AUTHENTIK_TOKEN"]
|
|
21
|
+
#
|
|
22
|
+
# @example config/environments/production.rb
|
|
23
|
+
# config.authentik_client.verify_ssl = true
|
|
24
|
+
#
|
|
25
|
+
# @example config/initializers/authentik_client.rb (traditional style, still works)
|
|
26
|
+
# Authentik::Client.configure do |config|
|
|
27
|
+
# config.host = "authentik.example.com"
|
|
28
|
+
# config.token = ENV["AUTHENTIK_TOKEN"]
|
|
29
|
+
# end
|
|
30
|
+
class Railtie < Rails::Railtie
|
|
31
|
+
config.authentik_client = Authentik::Client.configuration
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "authentik/api"
|
|
4
|
+
require "logger"
|
|
5
|
+
require "zeitwerk"
|
|
6
|
+
|
|
7
|
+
loader = Zeitwerk::Loader.for_gem_extension(Authentik)
|
|
8
|
+
loader.ignore("#{__dir__}/client/railtie.rb")
|
|
9
|
+
loader.setup
|
|
10
|
+
|
|
11
|
+
module Authentik
|
|
12
|
+
# Client provides a Ruby interface to the authentik API. It wraps the
|
|
13
|
+
# auto-generated OpenAPI client and organizes API calls into groups that
|
|
14
|
+
# correspond to the underlying API classes.
|
|
15
|
+
#
|
|
16
|
+
# API groups are accessed as methods on the client. Each group returns an
|
|
17
|
+
# {ApiProxy} that forwards method calls to the corresponding OpenAPI API
|
|
18
|
+
# class, stripping the redundant API group prefix for brevity.
|
|
19
|
+
#
|
|
20
|
+
# New API groups added to the underlying OpenAPI client are automatically
|
|
21
|
+
# discovered and available without changes to this class.
|
|
22
|
+
#
|
|
23
|
+
# @example Configure at startup and create a client
|
|
24
|
+
# Authentik::Client.configure do |config|
|
|
25
|
+
# config.host = "authentik.example.com"
|
|
26
|
+
# config.token = "your-api-token"
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# client = Authentik::Client.new
|
|
30
|
+
#
|
|
31
|
+
# @example Create a client with inline options
|
|
32
|
+
# client = Authentik::Client.new(
|
|
33
|
+
# host: "authentik.example.com",
|
|
34
|
+
# token: "your-api-token"
|
|
35
|
+
# )
|
|
36
|
+
#
|
|
37
|
+
# @example List all applications
|
|
38
|
+
# client.core.applications_list
|
|
39
|
+
#
|
|
40
|
+
# @example Get the admin version
|
|
41
|
+
# client.admin.version_retrieve
|
|
42
|
+
#
|
|
43
|
+
# @example List OAuth2 access tokens
|
|
44
|
+
# client.oauth2.access_tokens_list
|
|
45
|
+
class Client
|
|
46
|
+
# Yields the global {Configuration} object so that settings can be applied
|
|
47
|
+
# at startup (e.g., in a Rails initializer).
|
|
48
|
+
#
|
|
49
|
+
# @example
|
|
50
|
+
# Authentik::Client.configure do |config|
|
|
51
|
+
# config.host = "authentik.example.com"
|
|
52
|
+
# config.token = "your-api-token"
|
|
53
|
+
# end
|
|
54
|
+
#
|
|
55
|
+
# @yieldparam config [Configuration]
|
|
56
|
+
def self.configure
|
|
57
|
+
yield(configuration)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Returns the global {Configuration} instance, creating it on first call.
|
|
61
|
+
#
|
|
62
|
+
# @return [Configuration]
|
|
63
|
+
def self.configuration
|
|
64
|
+
@configuration ||= Configuration.new
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Resets the global configuration to a fresh {Configuration} instance.
|
|
68
|
+
#
|
|
69
|
+
# @return [Configuration]
|
|
70
|
+
def self.reset_configuration!
|
|
71
|
+
@configuration = Configuration.new
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @param host [String, nil] The authentik server hostname
|
|
75
|
+
# (e.g., +"authentik.example.com"+). Falls back to the value set in
|
|
76
|
+
# {.configuration} when not provided.
|
|
77
|
+
# @param token [String, nil] The API bearer token for authentication.
|
|
78
|
+
# Falls back to the value set in {.configuration} when not provided.
|
|
79
|
+
# @param scheme [String, nil] The URL scheme (+"https"+ or +"http"+).
|
|
80
|
+
# Falls back to the value set in {.configuration}, which defaults to
|
|
81
|
+
# +"https"+.
|
|
82
|
+
# @param options [Hash] Additional per-instance options forwarded to
|
|
83
|
+
# +Authentik::Api::Configuration+ (e.g., +verify_ssl: false+,
|
|
84
|
+
# +timeout: 60+). Take precedence over values set in {.configuration}.
|
|
85
|
+
# @raise [ArgumentError] if +host+ is not provided here or in the global
|
|
86
|
+
# configuration
|
|
87
|
+
# @raise [ArgumentError] if +token+ is not provided here or in the global
|
|
88
|
+
# configuration
|
|
89
|
+
def initialize(host: nil, token: nil, scheme: nil, **options)
|
|
90
|
+
cfg = self.class.configuration
|
|
91
|
+
resolved_host = host || cfg.host
|
|
92
|
+
resolved_token = token || cfg.access_token
|
|
93
|
+
resolved_scheme = scheme || cfg.scheme
|
|
94
|
+
|
|
95
|
+
raise ArgumentError, "host is required" if resolved_host.nil?
|
|
96
|
+
raise ArgumentError, "token is required" if resolved_token.nil?
|
|
97
|
+
|
|
98
|
+
@api_client = build_api_client(
|
|
99
|
+
cfg,
|
|
100
|
+
host: resolved_host,
|
|
101
|
+
token: resolved_token,
|
|
102
|
+
scheme: resolved_scheme,
|
|
103
|
+
**options
|
|
104
|
+
)
|
|
105
|
+
@api_instances = {}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Provides access to an API group by name. Returns an {ApiProxy} that
|
|
109
|
+
# wraps the corresponding OpenAPI API class instance.
|
|
110
|
+
#
|
|
111
|
+
# The method name is the API class name (without the +"Api"+ suffix)
|
|
112
|
+
# in lowercase. For example, +:core+ maps to +CoreApi+, +:admin+ to
|
|
113
|
+
# +AdminApi+, and +:oauth2+ to +OAuth2Api+.
|
|
114
|
+
#
|
|
115
|
+
# @return [ApiProxy] A proxy wrapping the underlying API class instance
|
|
116
|
+
# @raise [NoMethodError] if the name does not match any known API group
|
|
117
|
+
def method_missing(name, ...)
|
|
118
|
+
api_info = self.class.api_map[name]
|
|
119
|
+
return super unless api_info
|
|
120
|
+
|
|
121
|
+
@api_instances[name] ||= ApiProxy.new(api_info[:klass].new(@api_client), api_info[:prefix])
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def respond_to_missing?(name, include_private = false)
|
|
125
|
+
self.class.api_map.key?(name) || super
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Returns a hash mapping API group name symbols to their API class and
|
|
129
|
+
# prefix. Automatically discovers all classes in +Authentik::Api+
|
|
130
|
+
# that end with +"Api"+.
|
|
131
|
+
#
|
|
132
|
+
# @return [Hash{Symbol => Hash}]
|
|
133
|
+
def self.api_map
|
|
134
|
+
@api_map ||= Authentik::Api.constants
|
|
135
|
+
.select { |c| c.to_s.end_with?("Api") }
|
|
136
|
+
.filter_map do |c|
|
|
137
|
+
klass = Authentik::Api.const_get(c)
|
|
138
|
+
next unless klass.is_a?(Class)
|
|
139
|
+
|
|
140
|
+
base = c.to_s.delete_suffix("Api").downcase
|
|
141
|
+
[base.to_sym, {klass: klass, prefix: "#{base}_"}]
|
|
142
|
+
end
|
|
143
|
+
.to_h
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
private
|
|
147
|
+
|
|
148
|
+
def build_api_client(base_config, host:, token:, scheme:, **options)
|
|
149
|
+
config = base_config.dup
|
|
150
|
+
config.host = host
|
|
151
|
+
config.access_token = token
|
|
152
|
+
config.scheme = scheme
|
|
153
|
+
options.each { |k, v| config.public_send(:"#{k}=", v) if config.respond_to?(:"#{k}=") }
|
|
154
|
+
Authentik::Api::ApiClient.new(config)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
require "authentik/client/railtie" if defined?(Rails::Railtie)
|
data/mise.toml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[tools]
|
|
2
|
+
ruby = "3.3"
|
|
3
|
+
|
|
4
|
+
[tasks.ci]
|
|
5
|
+
description = "Run all CI tasks"
|
|
6
|
+
run = [
|
|
7
|
+
{ task = "rake:spec" },
|
|
8
|
+
{ tasks = ["rake:standard", "zizmor"] }
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
[tasks.zizmor]
|
|
12
|
+
description = "Static analysis for GitHub Actions."
|
|
13
|
+
run = "zizmor ./.github"
|
|
14
|
+
|
|
15
|
+
[tasks."zizmor:fix"]
|
|
16
|
+
description = "Run zizmor and auto fix."
|
|
17
|
+
run = "zizmor --fix=all ./.github"
|
|
18
|
+
|
|
19
|
+
[tasks.rake]
|
|
20
|
+
description = "Run the rake default tasks."
|
|
21
|
+
run = "rake"
|
|
22
|
+
|
|
23
|
+
[tasks."rake:spec"]
|
|
24
|
+
description = "Run specs."
|
|
25
|
+
run = "rake spec"
|
|
26
|
+
|
|
27
|
+
[tasks."rake:standard"]
|
|
28
|
+
description = "Run standardrb linting."
|
|
29
|
+
run = "rake standard"
|
metadata
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: authentik-client
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- David Uhlig
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-04-08 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: authentik-api
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: zeitwerk
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '2.6'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '2.6'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: irb
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rake
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '13.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '13.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: railties
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rspec
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '3.2'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '3.2'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: standard
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '1.3'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '1.3'
|
|
111
|
+
description: 'A developer-friendly Ruby wrapper around the auto-generated authentik-api
|
|
112
|
+
gem, offering an idiomatic interface for interacting with authentik configuration
|
|
113
|
+
objects and abstracting away the complexity of the underlying OpenAPI client.
|
|
114
|
+
|
|
115
|
+
'
|
|
116
|
+
email:
|
|
117
|
+
- david.uhlig@gmail.com
|
|
118
|
+
executables: []
|
|
119
|
+
extensions: []
|
|
120
|
+
extra_rdoc_files: []
|
|
121
|
+
files:
|
|
122
|
+
- CHANGELOG.md
|
|
123
|
+
- CODE_OF_CONDUCT.md
|
|
124
|
+
- LICENSE.md
|
|
125
|
+
- README.md
|
|
126
|
+
- Rakefile
|
|
127
|
+
- lib/authentik/api_proxy.rb
|
|
128
|
+
- lib/authentik/client.rb
|
|
129
|
+
- lib/authentik/client/configuration.rb
|
|
130
|
+
- lib/authentik/client/railtie.rb
|
|
131
|
+
- lib/authentik/client/version.rb
|
|
132
|
+
- mise.toml
|
|
133
|
+
homepage: https://github.com/david-uhlig/authentik-client
|
|
134
|
+
licenses:
|
|
135
|
+
- MIT
|
|
136
|
+
metadata:
|
|
137
|
+
allowed_push_host: https://rubygems.org
|
|
138
|
+
homepage_uri: https://github.com/david-uhlig/authentik-client
|
|
139
|
+
source_code_uri: https://github.com/david-uhlig/authentik-client
|
|
140
|
+
changelog_uri: https://github.com/david-uhlig/authentik-client/blob/main/CHANGELOG.md
|
|
141
|
+
post_install_message:
|
|
142
|
+
rdoc_options: []
|
|
143
|
+
require_paths:
|
|
144
|
+
- lib
|
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
146
|
+
requirements:
|
|
147
|
+
- - ">="
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: 3.3.0
|
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
|
+
requirements:
|
|
152
|
+
- - ">="
|
|
153
|
+
- !ruby/object:Gem::Version
|
|
154
|
+
version: '0'
|
|
155
|
+
requirements: []
|
|
156
|
+
rubygems_version: 3.5.22
|
|
157
|
+
signing_key:
|
|
158
|
+
specification_version: 4
|
|
159
|
+
summary: A developer-friendly Ruby wrapper for the authentik API that simplifies managing
|
|
160
|
+
authentik configuration objects.
|
|
161
|
+
test_files: []
|