Module: UnivapayClientSdk::AppJwt
- Defined in:
- lib/univapay_client_sdk/extensions.rb
Overview
── App token (JWT) claim decoding ────────────────────────────────────────
A UnivaPay app token JWT carries the context it was issued for. A
store-level token has both merchant_id and store_id; a merchant-level
token has only merchant_id.
Decoding only reads the payload segment -- it does NOT verify the signature, which is deliberate. The value is the caller's own credential, already trusted by virtue of being configured on the client; nothing here is an authorization decision. Never use these values to authenticate a third party's token.
Constant Summary collapse
- UUID_PATTERN =
Matches the canonical 8-4-4-4-12 hexadecimal UUID form.
/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i.freeze
Class Method Summary collapse
-
.decode_payload(jwt_token) ⇒ Hash?
Decodes the payload segment of a JWT without verifying its signature.
-
.read_uuid_claim(jwt_token, claim) ⇒ String?
Reads a claim from a JWT payload and returns it only if it is a UUID.
-
.require_store_id(store_id) ⇒ String
Asserts that a store id was resolvable from the configured app token.
Class Method Details
.decode_payload(jwt_token) ⇒ Hash?
Decodes the payload segment of a JWT without verifying its signature.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/univapay_client_sdk/extensions.rb', line 198 def self.decode_payload(jwt_token) return nil if jwt_token.nil? || !jwt_token.is_a?(String) || jwt_token.empty? segments = jwt_token.split('.', -1) return nil unless segments.length == 3 begin # unpack1('m0') is strict base64 and needs no `base64` gem, which stopped # being a default gem in Ruby 3.4. It requires correct padding, so # translate base64url to base64 and pad first. base64 = segments[1].tr('-_', '+/') base64 += '=' * ((4 - (base64.length % 4)) % 4) payload = JSON.parse(base64.unpack1('m0')) rescue ArgumentError, JSON::ParserError return nil end payload.is_a?(Hash) ? payload : nil end |
.read_uuid_claim(jwt_token, claim) ⇒ String?
Reads a claim from a JWT payload and returns it only if it is a UUID.
Anything else -- claim absent, nil, not a string, or a string that is not a canonical UUID -- yields nil, so a caller never has to distinguish "not set" from "could not decode".
226 227 228 229 230 231 232 |
# File 'lib/univapay_client_sdk/extensions.rb', line 226 def self.read_uuid_claim(jwt_token, claim) payload = decode_payload(jwt_token) return nil if payload.nil? value = payload[claim] value.is_a?(String) && UUID_PATTERN.match?(value) ? value : nil end |
.require_store_id(store_id) ⇒ String
Asserts that a store id was resolvable from the configured app token.
Named and shaped to match AppJwt.requireStoreId in the Java and PHP
SDKs, RequireStoreId in the C# one and requireStoreId in the
TypeScript and Python ones, so the guard reads the same in every language.
Returning the id (rather than fetching on the caller's behalf) keeps the
check ahead of every side effect.
246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/univapay_client_sdk/extensions.rb', line 246 def self.require_store_id(store_id) return store_id unless store_id.nil? # Says nothing about the token itself: the credential and its claims must # never reach an error message or a log. A merchant-level token reaching # here is not a broken token -- it is simply not scoped to a store. raise 'get_charge(charge_id) requires a store-level App Token: the ' \ 'configured token carries no usable "store_id" claim. Use a ' \ 'store-level App Token, or call get_charge(store_id, charge_id) ' \ 'on charges with an explicit store id.' end |