omniauth-xivauth 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/.github/dependabot.yml +19 -0
- data/.github/workflows/release.yml +55 -0
- data/.github/workflows/ruby.yml +107 -0
- data/.gitignore +101 -0
- data/.rubocop.yml +20 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +13 -0
- data/LICENSE.md +25 -0
- data/README.md +106 -0
- data/Rakefile +9 -0
- data/lib/omniauth/strategies/xivauth.rb +118 -0
- data/lib/omniauth/xivauth/version.rb +5 -0
- data/lib/omniauth/xivauth.rb +2 -0
- data/lib/omniauth-xivauth.rb +1 -0
- data/omniauth-xivauth.gemspec +29 -0
- metadata +93 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: af91e773acc4e5e73805012b91c57b5a7b259057f5b0de951b8555fa99d84f14
|
|
4
|
+
data.tar.gz: 98272562e841dacd01947a0b2ac83b08ad9277ac2dbbaf0b406591a06af1a2e8
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 717a1c7e81900360033c4f81cbe1b28a21b3a6ac03119e2c46a210fe2045e72dfe51666558c5c2035c95cea5606be141b983391b91ac21973aee9a994c1d39ae
|
|
7
|
+
data.tar.gz: 6b817bf5c26627cc3b4ca0a3e5db318f3bca6d40b464f405d88adb747631aee2519760979e14232485986ff82a4abbbb2b11f1c43882c0007b89832449497df6
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
updates:
|
|
4
|
+
- package-ecosystem: "bundler"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
groups:
|
|
9
|
+
ruby:
|
|
10
|
+
patterns:
|
|
11
|
+
- "*"
|
|
12
|
+
- package-ecosystem: "github-actions"
|
|
13
|
+
directory: "/"
|
|
14
|
+
schedule:
|
|
15
|
+
interval: "weekly"
|
|
16
|
+
groups:
|
|
17
|
+
gha:
|
|
18
|
+
patterns:
|
|
19
|
+
- "*"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
# smoke test: don't release a build that broke, somehow.
|
|
10
|
+
test:
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
timeout-minutes: 30
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v7
|
|
18
|
+
- name: Set up Ruby
|
|
19
|
+
uses: ruby/setup-ruby@v1
|
|
20
|
+
with:
|
|
21
|
+
ruby-version: 3.3
|
|
22
|
+
bundler-cache: true
|
|
23
|
+
- name: Run tests
|
|
24
|
+
run: bundle exec rake
|
|
25
|
+
|
|
26
|
+
release:
|
|
27
|
+
needs: test
|
|
28
|
+
if: github.repository == 'xivauth/omniauth-xivauth'
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
timeout-minutes: 10
|
|
31
|
+
|
|
32
|
+
permissions:
|
|
33
|
+
contents: write
|
|
34
|
+
id-token: write
|
|
35
|
+
packages: write
|
|
36
|
+
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v7
|
|
39
|
+
- name: Set up Ruby
|
|
40
|
+
uses: ruby/setup-ruby@v1
|
|
41
|
+
with:
|
|
42
|
+
bundler-cache: true
|
|
43
|
+
ruby-version: 3.3
|
|
44
|
+
- name: Release gem to RubyGems
|
|
45
|
+
uses: rubygems/release-gem@v1
|
|
46
|
+
- name: Push gem to GitHub Packages
|
|
47
|
+
env:
|
|
48
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
49
|
+
run: |
|
|
50
|
+
mkdir -p "$HOME/.gem"
|
|
51
|
+
printf -- '---\n:github: Bearer %s\n' "$GITHUB_TOKEN" > "$HOME/.gem/credentials"
|
|
52
|
+
chmod 0600 "$HOME/.gem/credentials"
|
|
53
|
+
gem push --key github \
|
|
54
|
+
--host "https://rubygems.pkg.github.com/${{ github.repository_owner }}" \
|
|
55
|
+
pkg/*.gem
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
name: Ruby
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: "Canonical Test Suite"
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
checks: write
|
|
15
|
+
code-quality: write
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
timeout-minutes: 30
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v7
|
|
20
|
+
- name: Set up Ruby
|
|
21
|
+
uses: ruby/setup-ruby@v1
|
|
22
|
+
with:
|
|
23
|
+
ruby-version: 3.3
|
|
24
|
+
bundler-cache: true
|
|
25
|
+
|
|
26
|
+
- name: Run tests
|
|
27
|
+
run: bundle exec rspec --format progress --format RspecJunitFormatter --out tmp/testresults/rspec.xml
|
|
28
|
+
env:
|
|
29
|
+
REPORT_TEST_RESULTS: true
|
|
30
|
+
SOFT_FAIL_TESTS: true
|
|
31
|
+
|
|
32
|
+
- name: Upload test results to Codecov
|
|
33
|
+
if: ${{ !cancelled() }}
|
|
34
|
+
uses: codecov/codecov-action@v7
|
|
35
|
+
with:
|
|
36
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
37
|
+
files: ./tmp/testresults/rspec.xml
|
|
38
|
+
report_type: test_results
|
|
39
|
+
|
|
40
|
+
- name: Upload coverage to Codecov
|
|
41
|
+
if: ${{ !cancelled() }}
|
|
42
|
+
uses: codecov/codecov-action@v7
|
|
43
|
+
with:
|
|
44
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
45
|
+
files: ./tmp/testresults/coverage/coverage.xml
|
|
46
|
+
report_type: coverage
|
|
47
|
+
|
|
48
|
+
- name: Upload coverage to GitHub
|
|
49
|
+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
|
50
|
+
uses: actions/upload-code-coverage@v1
|
|
51
|
+
with:
|
|
52
|
+
file: ./tmp/testresults/coverage/coverage.xml
|
|
53
|
+
language: Ruby
|
|
54
|
+
label: canonical
|
|
55
|
+
|
|
56
|
+
compat_test:
|
|
57
|
+
name: "Compatibility test: ${{ matrix.ruby }} on ${{ matrix.os }}"
|
|
58
|
+
permissions:
|
|
59
|
+
contents: read
|
|
60
|
+
checks: write
|
|
61
|
+
runs-on: ${{ matrix.os }}
|
|
62
|
+
timeout-minutes: 30
|
|
63
|
+
strategy:
|
|
64
|
+
fail-fast: false
|
|
65
|
+
matrix:
|
|
66
|
+
os: [ubuntu-latest]
|
|
67
|
+
ruby: [3.3, 3.4, 4.0]
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v7
|
|
70
|
+
- name: Set up Ruby
|
|
71
|
+
uses: ruby/setup-ruby@v1
|
|
72
|
+
with:
|
|
73
|
+
ruby-version: ${{ matrix.ruby }}
|
|
74
|
+
bundler-cache: true
|
|
75
|
+
- name: Set JRUBY_OPTS environment variable
|
|
76
|
+
run: echo "JRUBY_OPTS=--debug" >> "$GITHUB_ENV"
|
|
77
|
+
if: ${{ startsWith(matrix.ruby, 'jruby') }}
|
|
78
|
+
- name: Run tests
|
|
79
|
+
run: bundle exec rake
|
|
80
|
+
|
|
81
|
+
lint:
|
|
82
|
+
permissions:
|
|
83
|
+
contents: read
|
|
84
|
+
pull-requests: write
|
|
85
|
+
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
timeout-minutes: 10
|
|
88
|
+
steps:
|
|
89
|
+
- name: Checkout code
|
|
90
|
+
uses: actions/checkout@v7
|
|
91
|
+
|
|
92
|
+
- name: Install Ruby and gems
|
|
93
|
+
uses: ruby/setup-ruby@v1
|
|
94
|
+
with:
|
|
95
|
+
ruby-version: '4.0'
|
|
96
|
+
bundler-cache: true
|
|
97
|
+
|
|
98
|
+
- name: Generate binstubs
|
|
99
|
+
run: bundle binstubs rubocop
|
|
100
|
+
|
|
101
|
+
- name: Run rubocop with reviewdog
|
|
102
|
+
uses: reviewdog/action-rubocop@v2.22.0
|
|
103
|
+
with:
|
|
104
|
+
reporter: github-pr-review
|
|
105
|
+
only_changed: true
|
|
106
|
+
skip_install: true
|
|
107
|
+
use_bundler: true
|
data/.gitignore
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
### JetBrains template
|
|
2
|
+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
|
3
|
+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
4
|
+
|
|
5
|
+
# Just all of IDEA
|
|
6
|
+
.idea/
|
|
7
|
+
|
|
8
|
+
# CMake
|
|
9
|
+
cmake-build-*/
|
|
10
|
+
|
|
11
|
+
# Mongo Explorer plugin
|
|
12
|
+
.idea/**/mongoSettings.xml
|
|
13
|
+
|
|
14
|
+
# File-based project format
|
|
15
|
+
*.iws
|
|
16
|
+
|
|
17
|
+
# IntelliJ
|
|
18
|
+
out/
|
|
19
|
+
|
|
20
|
+
# mpeltonen/sbt-idea plugin
|
|
21
|
+
.idea_modules/
|
|
22
|
+
|
|
23
|
+
# JIRA plugin
|
|
24
|
+
atlassian-ide-plugin.xml
|
|
25
|
+
|
|
26
|
+
# Cursive Clojure plugin
|
|
27
|
+
.idea/replstate.xml
|
|
28
|
+
|
|
29
|
+
# SonarLint plugin
|
|
30
|
+
.idea/sonarlint/
|
|
31
|
+
|
|
32
|
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
33
|
+
com_crashlytics_export_strings.xml
|
|
34
|
+
crashlytics.properties
|
|
35
|
+
crashlytics-build.properties
|
|
36
|
+
fabric.properties
|
|
37
|
+
|
|
38
|
+
# Editor-based Rest Client
|
|
39
|
+
.idea/httpRequests
|
|
40
|
+
|
|
41
|
+
# Android studio 3.1+ serialized cache file
|
|
42
|
+
.idea/caches/build_file_checksums.ser
|
|
43
|
+
|
|
44
|
+
### Ruby template
|
|
45
|
+
*.gem
|
|
46
|
+
*.rbc
|
|
47
|
+
/.config
|
|
48
|
+
/coverage/
|
|
49
|
+
/InstalledFiles
|
|
50
|
+
/pkg/
|
|
51
|
+
/spec/reports/
|
|
52
|
+
/spec/examples.txt
|
|
53
|
+
/test/tmp/
|
|
54
|
+
/test/version_tmp/
|
|
55
|
+
/tmp/
|
|
56
|
+
|
|
57
|
+
# Used by dotenv library to load environment variables.
|
|
58
|
+
# .env
|
|
59
|
+
|
|
60
|
+
# Ignore Byebug command history file.
|
|
61
|
+
.byebug_history
|
|
62
|
+
|
|
63
|
+
## Specific to RubyMotion:
|
|
64
|
+
.dat*
|
|
65
|
+
.repl_history
|
|
66
|
+
build/
|
|
67
|
+
*.bridgesupport
|
|
68
|
+
build-iPhoneOS/
|
|
69
|
+
build-iPhoneSimulator/
|
|
70
|
+
|
|
71
|
+
## Specific to RubyMotion (use of CocoaPods):
|
|
72
|
+
#
|
|
73
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
|
74
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
|
75
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
|
76
|
+
#
|
|
77
|
+
# vendor/Pods/
|
|
78
|
+
|
|
79
|
+
## Documentation cache and generated files:
|
|
80
|
+
/.yardoc/
|
|
81
|
+
/_yardoc/
|
|
82
|
+
/doc/
|
|
83
|
+
/rdoc/
|
|
84
|
+
|
|
85
|
+
## Environment normalization:
|
|
86
|
+
/.bundle/
|
|
87
|
+
/vendor/bundle
|
|
88
|
+
/lib/bundler/man/
|
|
89
|
+
|
|
90
|
+
# for a library or gem, you might want to ignore these files since the code is
|
|
91
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
92
|
+
Gemfile.lock
|
|
93
|
+
.ruby-version
|
|
94
|
+
.ruby-gemset
|
|
95
|
+
|
|
96
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
|
97
|
+
.rvmrc
|
|
98
|
+
|
|
99
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
|
100
|
+
# .rubocop-https?--*
|
|
101
|
+
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
NewCops: enable
|
|
3
|
+
TargetRubyVersion: 3.3
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
Exclude:
|
|
6
|
+
- 'coverage/**/*'
|
|
7
|
+
- 'vendor/**/*'
|
|
8
|
+
|
|
9
|
+
Metrics:
|
|
10
|
+
Enabled: false
|
|
11
|
+
|
|
12
|
+
Style/Documentation:
|
|
13
|
+
Enabled: false
|
|
14
|
+
|
|
15
|
+
Style/FrozenStringLiteralComment:
|
|
16
|
+
EnforcedStyle: never
|
|
17
|
+
|
|
18
|
+
Naming/FileName:
|
|
19
|
+
Exclude:
|
|
20
|
+
- 'lib/omniauth-xivauth.rb'
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
Copyright © 2026, The XIVAuth Project
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person
|
|
7
|
+
obtaining a copy of this software and associated documentation
|
|
8
|
+
files (the “Software”), to deal in the Software without
|
|
9
|
+
restriction, including without limitation the rights to use,
|
|
10
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the
|
|
12
|
+
Software is furnished to do so, subject to the following
|
|
13
|
+
conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be
|
|
16
|
+
included in all copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
19
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
20
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
21
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
22
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
23
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
24
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
25
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# XIVAuth OmniAuth Strategy
|
|
2
|
+
|
|
3
|
+
Plug [XIVAuth](https://xivauth.net) into your Omniauth protected application
|
|
4
|
+
simply and efficiently. This strategy supports both user-based and
|
|
5
|
+
character-based flows.
|
|
6
|
+
|
|
7
|
+
Please be sure to refer to the [XIVAuth documentation](https://xivauth.net/developer/docs)
|
|
8
|
+
for information on how it provides OAuth2 services and how to use scopes.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
Add the following line to your application's Gemfile:
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
gem 'omniauth-xivauth'
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
This gem is standard for OmniAuth strategies. An example provider:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
|
24
|
+
provider :xivauth, ENV['XIVAUTH_CLIENT_ID'], ENV['XIVAUTH_CLIENT_SECRET'],
|
|
25
|
+
scope: 'user user:email character:all'
|
|
26
|
+
end
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
By default, this strategy will request the `user` scope. Additional scopes may
|
|
30
|
+
be requested through the `scope` option. Generally speaking, applications will
|
|
31
|
+
likely want one of `character`, `user`, or `user character:all`.
|
|
32
|
+
|
|
33
|
+
**Consumers must also take care to expect data in odd formats.** Users may
|
|
34
|
+
approve/reject certain scopes, or share many/one/no characters depending on
|
|
35
|
+
their preferences. Applications should be prepared to handle these cases
|
|
36
|
+
gracefully.
|
|
37
|
+
|
|
38
|
+
### Auth Hash Information
|
|
39
|
+
|
|
40
|
+
The format of the auth hash will differ based on the scope(s) requested, namely
|
|
41
|
+
whether `user` or `character` is chosen. In nearly all cases, the following
|
|
42
|
+
structure will be returned. Note that user information will not be returned
|
|
43
|
+
unless the `user` scope is requested and granted.
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
{
|
|
47
|
+
provider: "xivauth",
|
|
48
|
+
uid: "53f5faa3-3a9a-4d1e-91e5-80626b1a7da1", # user id
|
|
49
|
+
info: { # information about the user
|
|
50
|
+
name: "StandardUserTest",
|
|
51
|
+
email: "someuser@invalid.test", # nil unless `user:email` was granted and the address is verified
|
|
52
|
+
image: "https://cdn.xivauth.test/dummydata/standard-user-avatar.png"
|
|
53
|
+
},
|
|
54
|
+
extra: {
|
|
55
|
+
raw_info: {
|
|
56
|
+
# Alias of `extra.user` hash.
|
|
57
|
+
},
|
|
58
|
+
user: {
|
|
59
|
+
# API response from XIVAuth's /api/v1/user endpoint.
|
|
60
|
+
},
|
|
61
|
+
characters: nil # populated only if a character scope was granted
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
However, if an application is using just the `character` scope, the auth hash will instead present the chosen
|
|
67
|
+
character's identity as the authoritative object. This allows for applications that only care about character
|
|
68
|
+
information to treat inbound characters as their own first-class identities.
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
{
|
|
72
|
+
provider: "xivauth",
|
|
73
|
+
uid: "7bBfWdAGQYQ3mtHzalpgQOyFdTk", # character persistent key
|
|
74
|
+
info: {
|
|
75
|
+
name: "Mikoto Jinba",
|
|
76
|
+
image: "https://cdn.xivauth.test/dummydata/mikoto-portrait.png",
|
|
77
|
+
location: "Behemoth", # Home world of the character
|
|
78
|
+
urls: {
|
|
79
|
+
lodestone: "https://na.finalfantasyxiv.com/lodestone/character/32080755/"
|
|
80
|
+
},
|
|
81
|
+
lodestone_id: "32080755"
|
|
82
|
+
},
|
|
83
|
+
extra: {
|
|
84
|
+
raw_info: {
|
|
85
|
+
# Alias of `extra.characters` array's first (and only) element.
|
|
86
|
+
},
|
|
87
|
+
user: nil, # will always be null; this is a character-only auth hash
|
|
88
|
+
characters: [
|
|
89
|
+
{ "persistent_key" => "7bBfWdAGQYQ3mtHzalpgQOyFdTk", "name" => "Mikoto Jinba" }
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Contributing
|
|
96
|
+
|
|
97
|
+
Contributions are welcome! Feel free to submit Issues and PRs to improve this gem if you spot something that can be made
|
|
98
|
+
better. Note, however, that this gem is ultimately a transparent wrapper around the XIVAuth API. Upstream changes should
|
|
99
|
+
likely be filed against that project instead.
|
|
100
|
+
|
|
101
|
+
Please make sure tests pass (`bundle exec rspec`) and that Rubocop is happy (`bundle exec rubocop`) before submitting a
|
|
102
|
+
PR.
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
Licensed under the [MIT license](./LICENSE.md).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
require 'omniauth-oauth2'
|
|
2
|
+
|
|
3
|
+
module OmniAuth
|
|
4
|
+
module Strategies
|
|
5
|
+
class Xivauth < OmniAuth::Strategies::OAuth2
|
|
6
|
+
DEFAULT_SCOPE = 'user'.freeze
|
|
7
|
+
LODESTONE_CHARACTER_URL = 'https://na.finalfantasyxiv.com/lodestone/character/%s/'.freeze
|
|
8
|
+
|
|
9
|
+
option :name, 'xivauth'
|
|
10
|
+
|
|
11
|
+
option :client_options, {
|
|
12
|
+
site: 'https://xivauth.net/api/v1',
|
|
13
|
+
authorize_url: '/oauth/authorize',
|
|
14
|
+
token_url: '/oauth/token'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
option :authorize_options, [ :scope ]
|
|
18
|
+
|
|
19
|
+
info do
|
|
20
|
+
if user_data
|
|
21
|
+
{
|
|
22
|
+
name: user_data['display_name'],
|
|
23
|
+
email: user_data['email_verified'] ? user_data['email'] : nil,
|
|
24
|
+
image: user_data['avatar_url']
|
|
25
|
+
}
|
|
26
|
+
elsif character_only_login? && primary_character
|
|
27
|
+
{
|
|
28
|
+
name: primary_character['name'],
|
|
29
|
+
image: primary_character['portrait_url'],
|
|
30
|
+
location: primary_character['home_world'],
|
|
31
|
+
urls: {
|
|
32
|
+
lodestone: format(LODESTONE_CHARACTER_URL, primary_character['lodestone_id'])
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
# Not officially part of OmniAuth spec, but important enough to justify its own field.
|
|
36
|
+
lodestone_id: primary_character['lodestone_id']
|
|
37
|
+
}
|
|
38
|
+
else
|
|
39
|
+
{}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
uid do
|
|
44
|
+
if user_data
|
|
45
|
+
user_data['id']
|
|
46
|
+
elsif character_only_login? && primary_character
|
|
47
|
+
primary_character['persistent_key']
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
extra do
|
|
52
|
+
{
|
|
53
|
+
raw_info: user_data || primary_character,
|
|
54
|
+
user: user_data,
|
|
55
|
+
characters: character_data
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# NOTE: assumes the token response echoes back the granted scope as a
|
|
60
|
+
# space-delimited `scope` param, readable via `access_token.params`.
|
|
61
|
+
def granted_scopes
|
|
62
|
+
return @granted_scopes if defined?(@granted_scopes)
|
|
63
|
+
|
|
64
|
+
scope = access_token.params && access_token.params['scope']
|
|
65
|
+
@granted_scopes = scope.to_s.split
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def character_only_login?
|
|
69
|
+
# character and character:all are blocked by xivauth's server side, but we should still test for it.
|
|
70
|
+
granted_scopes.include?('character') && !user_scope_granted? &&
|
|
71
|
+
!(granted_scopes.include?('character:all') || granted_scopes.include?('character:manage'))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def user_scope_granted?
|
|
75
|
+
granted_scopes.include?('user') || granted_scopes.include?('user:manage')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def character_scope_granted?
|
|
79
|
+
granted_scopes.include?('character') || granted_scopes.include?('character:all') ||
|
|
80
|
+
granted_scopes.include?('character:manage')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Only fetched when the `user` scope was granted. The `user:email`
|
|
84
|
+
# scope only adds fields to this same payload, it doesn't change
|
|
85
|
+
# whether the request is made.
|
|
86
|
+
def user_data
|
|
87
|
+
return @user_data if defined?(@user_data)
|
|
88
|
+
|
|
89
|
+
@user_data = user_scope_granted? ? access_token.get('user').parsed : nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Fetched whenever the `character` scope was granted.
|
|
93
|
+
def character_data
|
|
94
|
+
return @character_data if defined?(@character_data)
|
|
95
|
+
|
|
96
|
+
@character_data = access_token.get('characters').parsed if character_scope_granted?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# The single character returned when `character` scope is granted
|
|
100
|
+
# without `user` scope (the character-only sign-in flow).
|
|
101
|
+
def primary_character
|
|
102
|
+
return nil if user_scope_granted? || !character_scope_granted?
|
|
103
|
+
|
|
104
|
+
character_data&.first
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def authorize_params
|
|
108
|
+
super.tap do |params|
|
|
109
|
+
options[:authorize_options].each do |option|
|
|
110
|
+
params[option] = request.params[option.to_s] if request.params[option.to_s]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
params[:scope] ||= DEFAULT_SCOPE
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'omniauth/xivauth'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
|
2
|
+
require 'omniauth/xivauth/version'
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |spec|
|
|
5
|
+
spec.name = 'omniauth-xivauth'
|
|
6
|
+
spec.version = Omniauth::Xivauth::VERSION
|
|
7
|
+
spec.authors = ['Kaz Wolfe', 'XIVAuth Development Team']
|
|
8
|
+
spec.email = %w[hi@wolf.dev support@xivauth.net]
|
|
9
|
+
|
|
10
|
+
spec.summary = 'XIVAuth strategy for OmniAuth'
|
|
11
|
+
spec.description = 'An OmniAuth strategy to authenticate users against XIVAuth, a third-party authentication ' \
|
|
12
|
+
'service for Final Fantasy XIV.'
|
|
13
|
+
spec.homepage = 'https://github.com/xivauth/omniauth-xivauth'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.metadata = {
|
|
16
|
+
'source_code_uri' => 'https://github.com/xivauth/omniauth-xivauth.git',
|
|
17
|
+
'changelog_uri' => 'https://github.com/xivauth/omniauth-xivauth/blob/main/CHANGELOG.md',
|
|
18
|
+
'github_repo' => 'ssh://github.com/xivauth/omniauth-xivauth',
|
|
19
|
+
'rubygems_mfa_required' => 'true',
|
|
20
|
+
}
|
|
21
|
+
spec.required_ruby_version = '>= 3.3'
|
|
22
|
+
|
|
23
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
|
|
24
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
25
|
+
spec.require_paths = ['lib']
|
|
26
|
+
|
|
27
|
+
spec.add_dependency 'omniauth', '~> 2.0'
|
|
28
|
+
spec.add_dependency 'omniauth-oauth2', '~> 1.8'
|
|
29
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: omniauth-xivauth
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kaz Wolfe
|
|
8
|
+
- XIVAuth Development Team
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2026-07-20 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: omniauth
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
requirements:
|
|
18
|
+
- - "~>"
|
|
19
|
+
- !ruby/object:Gem::Version
|
|
20
|
+
version: '2.0'
|
|
21
|
+
type: :runtime
|
|
22
|
+
prerelease: false
|
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
24
|
+
requirements:
|
|
25
|
+
- - "~>"
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
version: '2.0'
|
|
28
|
+
- !ruby/object:Gem::Dependency
|
|
29
|
+
name: omniauth-oauth2
|
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - "~>"
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '1.8'
|
|
35
|
+
type: :runtime
|
|
36
|
+
prerelease: false
|
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - "~>"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '1.8'
|
|
42
|
+
description: An OmniAuth strategy to authenticate users against XIVAuth, a third-party
|
|
43
|
+
authentication service for Final Fantasy XIV.
|
|
44
|
+
email:
|
|
45
|
+
- hi@wolf.dev
|
|
46
|
+
- support@xivauth.net
|
|
47
|
+
executables: []
|
|
48
|
+
extensions: []
|
|
49
|
+
extra_rdoc_files: []
|
|
50
|
+
files:
|
|
51
|
+
- ".github/dependabot.yml"
|
|
52
|
+
- ".github/workflows/release.yml"
|
|
53
|
+
- ".github/workflows/ruby.yml"
|
|
54
|
+
- ".gitignore"
|
|
55
|
+
- ".rubocop.yml"
|
|
56
|
+
- CHANGELOG.md
|
|
57
|
+
- Gemfile
|
|
58
|
+
- LICENSE.md
|
|
59
|
+
- README.md
|
|
60
|
+
- Rakefile
|
|
61
|
+
- lib/omniauth-xivauth.rb
|
|
62
|
+
- lib/omniauth/strategies/xivauth.rb
|
|
63
|
+
- lib/omniauth/xivauth.rb
|
|
64
|
+
- lib/omniauth/xivauth/version.rb
|
|
65
|
+
- omniauth-xivauth.gemspec
|
|
66
|
+
homepage: https://github.com/xivauth/omniauth-xivauth
|
|
67
|
+
licenses:
|
|
68
|
+
- MIT
|
|
69
|
+
metadata:
|
|
70
|
+
source_code_uri: https://github.com/xivauth/omniauth-xivauth.git
|
|
71
|
+
changelog_uri: https://github.com/xivauth/omniauth-xivauth/blob/main/CHANGELOG.md
|
|
72
|
+
github_repo: ssh://github.com/xivauth/omniauth-xivauth
|
|
73
|
+
rubygems_mfa_required: 'true'
|
|
74
|
+
post_install_message:
|
|
75
|
+
rdoc_options: []
|
|
76
|
+
require_paths:
|
|
77
|
+
- lib
|
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '3.3'
|
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - ">="
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '0'
|
|
88
|
+
requirements: []
|
|
89
|
+
rubygems_version: 3.5.22
|
|
90
|
+
signing_key:
|
|
91
|
+
specification_version: 4
|
|
92
|
+
summary: XIVAuth strategy for OmniAuth
|
|
93
|
+
test_files: []
|