omniauth-line-oidc 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8f26151039d5a4335bc74e131925ce65064ab85e8d82597d1944bad71c22b283
4
+ data.tar.gz: bb091bb1368f5efbfceb229914c646b89a2945cb7441f7be00c7815c1efa1490
5
+ SHA512:
6
+ metadata.gz: 3e63eee133d0243a9369dc39883a7ea09e8aa6eccaac857c03a4c15215bb9863c1ab62f08e0e72f3de60098969ae79f329409c7996d33771a953ed84fa2b24be
7
+ data.tar.gz: bdb9da23b3657c86127991e2e81acd67a301bd006aa2bbda12e2639937a216ede80919351afe3ef3e1f0c5dd305fafc0b8af339b8c47770e2efd76267d06a5a2
data/CHANGELOG.md ADDED
@@ -0,0 +1,54 @@
1
+ # Changelog
2
+
3
+ All notable changes to this gem are recorded here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the gem follows
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [1.0.0] - 2026-11-12
10
+
11
+ First release under the name `omniauth-line-oidc`. The gem continues the
12
+ `omniauth-line` strategy (last released as 0.1.0 in 2021) and keeps its
13
+ provider name, `:line`, so an app can switch by changing its Gemfile.
14
+
15
+ ### Added
16
+
17
+ - A `nonce` is generated for every authorization request that asks for an
18
+ ID token, kept in the session under the request's `state`, and sent to
19
+ LINE's verify endpoint with the ID token on the callback.
20
+ - The sign-in fails with `invalid_credentials` when LINE rejects the ID
21
+ token, for its nonce or anything else.
22
+ - PKCE (`S256`) is on by default. Turn it off with `pkce: false`.
23
+ - `extra[:id_token_claims]`: the ID token's claims as LINE's verify
24
+ endpoint returned them, including `amr`. Present only for a verified
25
+ token.
26
+ - `extra[:raw_info]`: the profile API response.
27
+ - `extra[:friendship_status_changed]`, when LINE reports it on the callback
28
+ (`bot_prompt`).
29
+ - The sign-in fails with `invalid_credentials` when the verified ID token
30
+ names a different user than the profile.
31
+
32
+ ### Changed since `omniauth-line` 0.1.0
33
+
34
+ - Token exchange sends the channel secret in the request body, one of the
35
+ two client authentication methods LINE documents.
36
+ - The authorization URL and the API calls use their own hosts
37
+ (`access.line.me` and `api.line.me`) from fixed settings; nothing is
38
+ rewritten per request.
39
+ - `info[:email]` is read from the ID token through LINE's verify endpoint.
40
+ When the endpoint cannot be reached, times out or answers with a server
41
+ error, the email is `nil` and the sign-in carries on.
42
+ - The verify call has timeouts (5 s to open, 10 s to read), configurable
43
+ through `verify_options`.
44
+ - LINE's authorization options are forwarded when set: `prompt`, `max_age`,
45
+ `ui_locales`, `bot_prompt`, `initial_amr_display`, `switch_amr`,
46
+ `disable_auto_login`, `disable_ios_auto_login`. A `nonce` option is
47
+ ignored; the strategy generates one per sign-in.
48
+ - The callback URL override is the `redirect_uri` option. `callback_url`,
49
+ the name `omniauth-line` 0.1.0 used, is still accepted.
50
+ - A profile response that is not JSON, or names no user, fails the sign-in
51
+ with `invalid_credentials`.
52
+ - Requires Ruby 3.1 or newer, `omniauth` 2.3.1 or newer and
53
+ `omniauth-oauth2` 1.10 or newer. The `json` gem is no longer a declared
54
+ dependency.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 kazasiki and the omniauth-line contributors
4
+ Copyright (c) 2026 the omniauth-line-oidc contributors
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,221 @@
1
+ # omniauth-line-oidc
2
+
3
+ [![CI](https://github.com/momiji-rs/omniauth-line-oidc/actions/workflows/ci.yml/badge.svg)](https://github.com/momiji-rs/omniauth-line-oidc/actions/workflows/ci.yml)
4
+
5
+ LINE Login v2.1 (OAuth 2.0 / OpenID Connect) strategy for OmniAuth.
6
+
7
+ See the LINE Login docs for details:
8
+ https://developers.line.biz/en/docs/line-login/integrate-line-login/
9
+
10
+ This gem continues the `omniauth-line` strategy, which has had no release
11
+ since 2021. It registers the same provider name, `:line`.
12
+
13
+ ## Using This Strategy
14
+
15
+ First start by adding this gem to your Gemfile:
16
+
17
+ ```ruby
18
+ gem 'omniauth-line-oidc'
19
+ ```
20
+
21
+ ### Switching from `omniauth-line`
22
+
23
+ Replace the gem in your Gemfile; the provider name, the callback path
24
+ (`/auth/line/callback`) and the auth hash keys are the same. Things to
25
+ check:
26
+
27
+ - PKCE is on by default. It needs nothing from you unless your callback is
28
+ handled without the session that started the sign-in; see
29
+ [Callbacks handled by another session](#callbacks-handled-by-another-session).
30
+ - A sign-in started before the deploy and finished after it has no PKCE
31
+ verifier or nonce in its session, and may be refused by LINE; the user
32
+ signs in again.
33
+ - A sign-in now fails when LINE rejects the ID token. `omniauth-line`
34
+ ignored the rejection and returned no email.
35
+ - `extra` now also carries `raw_info`, and `id_token_claims` when the ID
36
+ token was verified.
37
+ - Do not keep both gems in one bundle: both define
38
+ `OmniAuth::Strategies::Line`. If you require the gem by name, the file
39
+ is `omniauth-line-oidc`.
40
+ - Requires `omniauth-oauth2` 1.10 or newer.
41
+
42
+ See the [changelog](CHANGELOG.md) for everything that differs from
43
+ `omniauth-line` 0.1.0.
44
+
45
+ Next, tell OmniAuth about this provider. For a Rails app, your
46
+ `config/initializers/omniauth.rb` file should look like this:
47
+
48
+ ```ruby
49
+ Rails.application.config.middleware.use OmniAuth::Builder do
50
+ provider :line, ENV['LINE_CHANNEL_ID'], ENV['LINE_CHANNEL_SECRET']
51
+ end
52
+ ```
53
+
54
+ Register your callback URL (e.g. `https://your.app/auth/line/callback`)
55
+ under "LINE Login > Callback URL" in the
56
+ [LINE Developers console](https://developers.line.biz/console/), or the
57
+ authorization request will fail with "Invalid redirect_uri value".
58
+
59
+ ### Scopes and email
60
+
61
+ The default scope is `profile openid`. To receive the user's email
62
+ address, apply for the "OpenID Connect email" permission in the LINE
63
+ Developers console and request the `email` scope:
64
+
65
+ ```ruby
66
+ provider :line, ENV['LINE_CHANNEL_ID'], ENV['LINE_CHANNEL_SECRET'],
67
+ scope: 'profile openid email'
68
+ ```
69
+
70
+ LINE only exposes the email inside the ID token, never through the
71
+ profile API. When the `email` scope is not granted, `info[:email]` is
72
+ `nil`.
73
+
74
+ ### Options
75
+
76
+ Besides the standard OmniAuth options, the strategy forwards these to
77
+ LINE's authorization URL when you set them: `prompt`, `max_age`,
78
+ `ui_locales`, `bot_prompt`, `initial_amr_display`, `switch_amr`,
79
+ `disable_auto_login`, `disable_ios_auto_login`. There is no `nonce`
80
+ option: the strategy generates a fresh one for every sign-in.
81
+
82
+ ```ruby
83
+ provider :line, ENV['LINE_CHANNEL_ID'], ENV['LINE_CHANNEL_SECRET'],
84
+ bot_prompt: 'normal', ui_locales: 'ja'
85
+ ```
86
+
87
+ | Option | Default | Meaning |
88
+ |---|---|---|
89
+ | `scope` | `'profile openid'` | Add `email` once the channel has the permission |
90
+ | `pkce` | `true` | Send a PKCE challenge (`S256`, the only method LINE accepts) |
91
+ | `redirect_uri` | built from the request | The callback URL registered with LINE. `callback_url`, the name `omniauth-line` used, is accepted too |
92
+ | `verify_options` | `{ open_timeout: 5, read_timeout: 10 }` | Timeouts for the ID token verify call, in seconds |
93
+
94
+ `response_mode` is not supported: the strategy reads the callback from
95
+ the query string, which is LINE's default.
96
+
97
+ ## How the ID token is used
98
+
99
+ The user is identified by LINE's profile API, called with the access
100
+ token the sign-in was just issued. The ID token adds what the profile
101
+ API does not have, the email above all.
102
+
103
+ - The strategy sends a `nonce` with every authorization request that
104
+ asks for an ID token, and keeps it in the session under the request's
105
+ `state`.
106
+ - On the callback it sends the ID token, the channel ID and that nonce
107
+ to LINE's [verify endpoint](https://developers.line.biz/en/reference/line-login/#verify-id-token).
108
+ LINE checks the signature, issuer, audience, expiry and nonce.
109
+ - If LINE rejects the token (HTTP 400, which is also its answer to a
110
+ wrong nonce), the sign-in fails with `invalid_credentials`.
111
+ - If the verified token names a different user than the profile, the
112
+ sign-in fails with `invalid_credentials`.
113
+ - If LINE cannot be asked (the call times out, the connection fails, or
114
+ LINE answers with a server error), the sign-in continues without the
115
+ claims: `info[:email]` is `nil` and `extra[:id_token_claims]` is
116
+ absent. A warning is logged. Handle a `nil` email as you already must
117
+ for a user who declines the `email` scope.
118
+
119
+ The raw `extra[:id_token]` is passed through as LINE issued it. Do not
120
+ read claims out of it yourself; use `extra[:id_token_claims]`, which is
121
+ only present after verification.
122
+
123
+ The strategy keeps one nonce for each sign-in a browser session has
124
+ under way, up to five, next to what `omniauth-oauth2` stores for state
125
+ and PKCE. Five unfinished sign-ins come to about 2.5 KB of session data,
126
+ which matters if your sessions live in a 4 KB cookie that is already
127
+ well filled.
128
+
129
+ ### Callbacks handled by another session
130
+
131
+ The nonce and the PKCE verifier live in the session that started the
132
+ sign-in. If your callback arrives in a different session (for example a
133
+ front end on another domain relays it to your API), the strategy cannot
134
+ find them:
135
+
136
+ - Set `pkce: false`, or the token exchange is sent without a verifier
137
+ and LINE rejects it.
138
+ - The ID token is then verified without a nonce. Everything else about
139
+ it is still checked.
140
+ - You will also need `provider_ignores_state: true`, which gives up the
141
+ CSRF protection `state` provides. Prefer carrying the session across
142
+ if you can.
143
+
144
+ ## Authentication Hash
145
+
146
+ An example auth hash available in `request.env['omniauth.auth']`:
147
+
148
+ ```ruby
149
+ {
150
+ provider: "line",
151
+ uid: "U1234567890abcdef1234567890abcdef",
152
+ info: {
153
+ name: "yamada tarou",
154
+ image: "https://profile.line-scdn.net/xxxxx",
155
+ description: nil, # the user's status message, may be nil
156
+ email: "user@example.com" # nil unless the email scope is granted
157
+ },
158
+ credentials: {
159
+ token: "a1b2c3d4...", # OAuth 2.0 access token
160
+ refresh_token: "e5f6g7h8...",
161
+ expires_at: 1789266388,
162
+ expires: true
163
+ },
164
+ extra: {
165
+ raw_info: { # the profile API response
166
+ "userId" => "U1234567890abcdef1234567890abcdef",
167
+ "displayName" => "yamada tarou",
168
+ "pictureUrl" => "https://profile.line-scdn.net/xxxxx"
169
+ },
170
+ id_token: "eyJ0eXAiOiJKV1Qi...", # as issued; present with the openid scope
171
+ id_token_claims: { # present only when LINE verified the token
172
+ "iss" => "https://access.line.me",
173
+ "sub" => "U1234567890abcdef1234567890abcdef",
174
+ "aud" => "1234567890",
175
+ "exp" => 1789266388,
176
+ "iat" => 1789262788,
177
+ "nonce" => "0f3c...",
178
+ "amr" => ["linesso"], # how the user authenticated
179
+ "name" => "yamada tarou",
180
+ "email" => "user@example.com"
181
+ },
182
+ friendship_status_changed: true # present only when bot_prompt was requested
183
+ }
184
+ }
185
+ ```
186
+
187
+ ## Development
188
+
189
+ ```sh
190
+ bundle install
191
+ bundle exec rake # runs the specs; every line of lib/ must be covered
192
+ ```
193
+
194
+ The test suite stubs all HTTP with WebMock; no LINE credentials are
195
+ needed. CI runs the suite on Ruby 3.1 through 4.0 and on ruby-head
196
+ (which may fail without failing the build), and once more against the
197
+ oldest dependency versions the gemspec admits:
198
+
199
+ ```sh
200
+ BUNDLE_GEMFILE=gemfiles/minimum.gemfile bundle install
201
+ BUNDLE_GEMFILE=gemfiles/minimum.gemfile bundle exec rake
202
+ ```
203
+
204
+ ## Releasing
205
+
206
+ Releases are published by the `Release` workflow through RubyGems
207
+ [trusted publishing](https://guides.rubygems.org/trusted-publishing/);
208
+ no API key is stored in the repository. Only 1.0.0, which created the
209
+ gem on RubyGems.org, was pushed by hand.
210
+
211
+ 1. Set the version in `lib/omniauth/line_oidc/version.rb` and move the
212
+ changelog's "Unreleased" entries under that version. Merge to `master`.
213
+ 2. Tag that commit `v<version>` and push the tag.
214
+ 3. The workflow checks that the tag matches the gem's version and that
215
+ the commit is on `master`, runs the specs, then builds and pushes the
216
+ gem.
217
+
218
+ One-time setup on RubyGems.org, by an owner of the gem: a trusted
219
+ publisher for repository `momiji-rs/omniauth-line-oidc`, workflow
220
+ `release.yml`, environment `release`, added on the gem's "Trusted
221
+ publishers" page.
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
4
+ module LineOidc
5
+ VERSION = '1.0.0'
6
+ end
7
+ end
@@ -0,0 +1,227 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth-oauth2'
4
+ require 'json'
5
+ require 'net/http'
6
+ require 'openssl'
7
+ require 'securerandom'
8
+
9
+ module OmniAuth
10
+ module Strategies
11
+ # LINE Login v2.1.
12
+ #
13
+ # The user is identified by the profile API, called with the access token
14
+ # this sign-in was just issued. The ID token adds claims the profile API
15
+ # does not have (the email above all). Its claims are used only after
16
+ # LINE's verify endpoint has accepted the token, together with the nonce
17
+ # this strategy sent. A token LINE rejects fails the sign-in; a verify
18
+ # endpoint that cannot be reached leaves the sign-in working without the
19
+ # claims.
20
+ class Line < OmniAuth::Strategies::OAuth2
21
+ VERIFY_URL = 'https://api.line.me/oauth2/v2.1/verify'
22
+ NONCE_SESSION_KEY = 'omniauth.line.nonces'
23
+ # Sign-ins a browser session can have under way at once, each with its
24
+ # own nonce; the oldest is dropped beyond this.
25
+ MAX_STORED_NONCES = 5
26
+
27
+ # Failures that say nothing about the token: LINE was not reached, or
28
+ # did not answer.
29
+ VERIFY_UNREACHABLE = [
30
+ ::Timeout::Error, ::SystemCallError, ::SocketError, ::IOError, ::OpenSSL::SSL::SSLError
31
+ ].freeze
32
+
33
+ option :name, 'line'
34
+ option :scope, 'profile openid'
35
+
36
+ # LINE supports PKCE with S256 only, which is what omniauth-oauth2 sends.
37
+ # Set `pkce: false` when the callback is handled without the session
38
+ # that started the sign-in, since the verifier lives in that session.
39
+ option :pkce, true
40
+
41
+ # omniauth-oauth2 only forwards options named here to the authorize
42
+ # URL; anything else set on the strategy is silently dropped. `nonce` is
43
+ # absent on purpose: a nonce configured once would be the same for every
44
+ # sign-in, so the strategy always generates its own.
45
+ option :authorize_options, %i[
46
+ scope state prompt max_age ui_locales bot_prompt
47
+ initial_amr_display switch_amr disable_auto_login
48
+ disable_ios_auto_login
49
+ ]
50
+
51
+ # The verify call runs inside the user-facing callback request, so a
52
+ # slow LINE API must fail fast rather than hold the login hostage.
53
+ DEFAULT_VERIFY_TIMEOUTS = { open_timeout: 5, read_timeout: 10 }.freeze
54
+ option :verify_options, DEFAULT_VERIFY_TIMEOUTS.dup
55
+
56
+ # Authorization lives on access.line.me while every API call
57
+ # (token exchange, profile, verify) lives on api.line.me.
58
+ option :client_options, {
59
+ site: 'https://api.line.me',
60
+ authorize_url: 'https://access.line.me/oauth2/v2.1/authorize',
61
+ token_url: '/oauth2/v2.1/token',
62
+ auth_scheme: :request_body
63
+ }
64
+
65
+ uid do
66
+ ensure_id_token_is_for_this_user!
67
+ raw_info['userId']
68
+ end
69
+
70
+ info do
71
+ {
72
+ name: raw_info['displayName'],
73
+ image: raw_info['pictureUrl'],
74
+ description: raw_info['statusMessage'],
75
+ email: email
76
+ }
77
+ end
78
+
79
+ extra do
80
+ hash = { raw_info: raw_info }
81
+ hash[:id_token] = id_token if id_token
82
+ hash[:id_token_claims] = id_token_claims unless id_token_claims.empty?
83
+ hash[:friendship_status_changed] = friendship_status_changed unless friendship_status_changed.nil?
84
+ hash
85
+ end
86
+
87
+ # A nonce ties the ID token to this sign-in: it is sent with the
88
+ # authorization request, LINE copies it into the ID token, and the
89
+ # verify call later states which nonce the token must carry.
90
+ def authorize_params
91
+ super.tap do |params|
92
+ next unless openid_scope?(params[:scope])
93
+
94
+ params[:nonce] = SecureRandom.hex(16)
95
+ remember_nonce(params[:state], params[:nonce])
96
+ end
97
+ end
98
+
99
+ # The nonce is taken before anything can fail, so a callback that is
100
+ # refused or carries an error leaves none behind.
101
+ def callback_phase
102
+ @nonce = take_nonce
103
+ super
104
+ end
105
+
106
+ # LINE returns the email claim only inside the ID token (email scope),
107
+ # never from the profile endpoint.
108
+ def email
109
+ id_token_claims['email']
110
+ end
111
+
112
+ # The ID token's claims as LINE's verify endpoint returned them, or an
113
+ # empty hash when there is no ID token or LINE could not be asked.
114
+ def id_token_claims
115
+ @id_token_claims ||= id_token ? verified_claims : {}
116
+ end
117
+
118
+ # Require: Access token with PROFILE permission issued.
119
+ def raw_info
120
+ @raw_info ||= fetch_profile
121
+ end
122
+
123
+ # `callback_url` is the option name omniauth-line 0.1.0 used.
124
+ def callback_url
125
+ options[:redirect_uri] || options[:callback_url] || (full_host + script_name + callback_path)
126
+ end
127
+
128
+ private
129
+
130
+ def id_token
131
+ access_token['id_token']
132
+ end
133
+
134
+ # Set by LINE on the callback only when `bot_prompt` was requested.
135
+ def friendship_status_changed
136
+ value = request.params['friendship_status_changed']
137
+ value.nil? ? nil : value.to_s == 'true'
138
+ end
139
+
140
+ def openid_scope?(scope)
141
+ scope.to_s.split(/[\s,]+/).include?('openid')
142
+ end
143
+
144
+ def fetch_profile
145
+ profile = parse_json(access_token.get('v2/profile').body)
146
+ return profile if profile.is_a?(Hash) && profile['userId']
147
+
148
+ raise CallbackError.new(:invalid_credentials, 'the profile response names no user')
149
+ end
150
+
151
+ # The profile comes from the access token and the claims from the ID
152
+ # token; both were issued by the same token response, so they name the
153
+ # same user unless something is badly wrong.
154
+ def ensure_id_token_is_for_this_user!
155
+ subject = id_token_claims['sub']
156
+ return if subject.nil? || subject == raw_info['userId']
157
+
158
+ raise CallbackError.new(:invalid_credentials, 'the ID token and the profile name different users')
159
+ end
160
+
161
+ def verified_claims
162
+ response = verify_id_token
163
+ payload = parse_json(response.body)
164
+
165
+ if response.is_a?(Net::HTTPSuccess)
166
+ return payload if payload.is_a?(Hash) && payload['sub']
167
+
168
+ log :warn, 'ID token verify returned no claims'
169
+ elsif response.is_a?(Net::HTTPBadRequest)
170
+ # LINE's answer for a token that fails a check, the nonce included.
171
+ description = payload['error_description'] || payload['error'] if payload.is_a?(Hash)
172
+ raise CallbackError.new(:invalid_credentials, "LINE rejected the ID token: #{description}")
173
+ else
174
+ log :warn, "ID token verify unavailable (HTTP #{response.code})"
175
+ end
176
+ {}
177
+ rescue *VERIFY_UNREACHABLE => e
178
+ log :warn, "ID token verify could not be reached (#{e.class})"
179
+ {}
180
+ end
181
+
182
+ def verify_id_token
183
+ uri = URI(VERIFY_URL)
184
+ request = Net::HTTP::Post.new(uri)
185
+ form = { id_token: id_token, client_id: client.id }
186
+ form[:nonce] = @nonce if @nonce
187
+ request.set_form_data(form)
188
+ timeouts = options.verify_options || {}
189
+ Net::HTTP.start(uri.host, uri.port,
190
+ use_ssl: true,
191
+ open_timeout: timeouts[:open_timeout] || DEFAULT_VERIFY_TIMEOUTS[:open_timeout],
192
+ read_timeout: timeouts[:read_timeout] || DEFAULT_VERIFY_TIMEOUTS[:read_timeout]) do |http|
193
+ http.request(request)
194
+ end
195
+ end
196
+
197
+ def parse_json(body)
198
+ JSON.parse(body.to_s)
199
+ rescue JSON::ParserError
200
+ nil
201
+ end
202
+
203
+ # Nonces are kept per `state`, so two sign-ins started in one browser
204
+ # session each verify against their own.
205
+ def remember_nonce(state, nonce)
206
+ nonces = stored_nonces
207
+ nonces.delete(state.to_s)
208
+ nonces[state.to_s] = nonce.to_s
209
+ session[NONCE_SESSION_KEY] = nonces.to_a.last(MAX_STORED_NONCES).to_h
210
+ end
211
+
212
+ # nil when this callback's session did not start the sign-in; the
213
+ # verify call then checks everything about the token except the nonce.
214
+ def take_nonce
215
+ nonces = stored_nonces
216
+ nonce = nonces.delete(request.params['state'].to_s)
217
+ session[NONCE_SESSION_KEY] = nonces if nonce
218
+ nonce
219
+ end
220
+
221
+ def stored_nonces
222
+ nonces = session[NONCE_SESSION_KEY]
223
+ nonces.is_a?(Hash) ? nonces.dup : {}
224
+ end
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth/line_oidc/version'
4
+ require 'omniauth/strategies/line'
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-line-oidc
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - kazasiki
8
+ - omniauth-line-oidc contributors
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: omniauth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.3.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.3.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: omniauth-oauth2
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.10'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.10'
47
+ description: 'Sign in with LINE through OmniAuth: LINE Login v2.1 with OpenID Connect,
48
+ including the email claim and LINE-specific authorization options.'
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - CHANGELOG.md
54
+ - LICENSE.txt
55
+ - README.md
56
+ - lib/omniauth-line-oidc.rb
57
+ - lib/omniauth/line_oidc/version.rb
58
+ - lib/omniauth/strategies/line.rb
59
+ homepage: https://github.com/momiji-rs/omniauth-line-oidc
60
+ licenses:
61
+ - MIT
62
+ metadata:
63
+ source_code_uri: https://github.com/momiji-rs/omniauth-line-oidc/tree/master
64
+ changelog_uri: https://github.com/momiji-rs/omniauth-line-oidc/blob/master/CHANGELOG.md
65
+ bug_tracker_uri: https://github.com/momiji-rs/omniauth-line-oidc/issues
66
+ rubygems_mfa_required: 'true'
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '3.1'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubygems_version: 3.6.9
82
+ specification_version: 4
83
+ summary: OmniAuth strategy for LINE Login v2.1 (OpenID Connect)
84
+ test_files: []