auth_jwt_go 1.0.3 → 1.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 +4 -4
- data/AGENTS.md +114 -0
- data/CLAUDE.md +12 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +60 -22
- data/README.md +28 -2
- data/auth_jwt_go.gemspec +5 -1
- data/lib/auth_jwt_go/version.rb +1 -1
- data/lib/auth_jwt_go.rb +44 -13
- metadata +26 -23
- data/.idea/.gitignore +0 -8
- data/.idea/.rakeTasks +0 -7
- data/.idea/auth_jwt_go.iml +0 -18
- data/.idea/misc.xml +0 -7
- data/.idea/modules.xml +0 -8
- data/.idea/vcs.xml +0 -6
- data/auth_jwt_go-0.1.0.gem +0 -0
- data/auth_jwt_go-0.1.1.gem +0 -0
- data/auth_jwt_go-0.1.2.gem +0 -0
- data/auth_jwt_go-0.1.3.gem +0 -0
- data/auth_jwt_go-0.1.4.gem +0 -0
- data/auth_jwt_go-1.0.0.gem +0 -0
- data/auth_jwt_go-1.0.1.gem +0 -0
- data/auth_jwt_go-1.0.2.gem +0 -0
- data/bin/console +0 -14
- data/bin/setup +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 985e7c4f4d0a83265f060d016883b377db4b1bb72850889aac2c9353ae24a2d4
|
|
4
|
+
data.tar.gz: e3e4995f9be5ce40baad5ce925070203dc4099fa8f3e61213193bb0e9e8a2b0d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aaa3fa589123eaf00276a0d302634f05f42deea92cb2f9189f84cdeb3d7f0be772918a4d73675688a72cd80a829c23edaa6069a51329c93ef62a74b62cd9c2a0
|
|
7
|
+
data.tar.gz: f05f024cfefb91da34ec0866aa279fed48e426297d621833e7a117e240e2c959d93df365056c496de95184003f1a174638b7bb096487219558e9d7ba64c2e048
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# AGENTS.md — auth_jwt_go
|
|
2
|
+
|
|
3
|
+
Guía para agentes de IA y personas nuevas en el repositorio. Este archivo es la fuente canónica; `CLAUDE.md` lo importa y solo agrega notas específicas de Claude Code.
|
|
4
|
+
|
|
5
|
+
## Qué es este proyecto
|
|
6
|
+
|
|
7
|
+
`auth_jwt_go` es una **gema Ruby para Rails** (no es un proyecto Go, a pesar del nombre). Provee un módulo `AuthJwtGo` que se incluye en un controlador base de una API Rails para:
|
|
8
|
+
|
|
9
|
+
- **Autenticar la aplicación cliente** mediante un header `Api-Token` comparado contra `secret_key_api` (`before_action :authorized_app`).
|
|
10
|
+
- **Identificar al usuario** a partir de un JWT enviado en el header `Authorization: Bearer <token>` (`before_action :authorized_user`), exponiendo el helper `current_user`.
|
|
11
|
+
- **Emitir JWTs** con `encode_token(payload)`.
|
|
12
|
+
- **Decodificar un JWT de otro request** (`decoded_tenant(http_request)`), pensado para comunicación entre microservicios.
|
|
13
|
+
|
|
14
|
+
Está publicada en RubyGems como `auth_jwt_go`. Versión actual: ver `lib/auth_jwt_go/version.rb` (1.1.0). Repositorio público: https://github.com/remolacho/auth_jwt_go.
|
|
15
|
+
|
|
16
|
+
## Estructura
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
lib/auth_jwt_go.rb # Módulo principal: configuración + métodos de autenticación
|
|
20
|
+
lib/auth_jwt_go/version.rb # AuthJwtGo::VERSION
|
|
21
|
+
lib/auth_jwt_go/authorized_user.rb # Objeto dinámico construido desde el payload del JWT
|
|
22
|
+
lib/generators/auth_jwt_go/install_generator.rb # rails g auth_jwt_go:install → config/initializers/init_auth_jwt.rb
|
|
23
|
+
lib/generators/auth_jwt_go/test_helper_generator.rb # rails g auth_jwt_go:test_helper → spec/support/request_helpers.rb
|
|
24
|
+
lib/generators/auth_jwt_go/templates/ # Plantillas que copian los generadores
|
|
25
|
+
spec/ # RSpec
|
|
26
|
+
auth_jwt_go.gemspec, Gemfile, Rakefile # Empaquetado y tareas
|
|
27
|
+
*.gem # Builds históricos commiteados en la raíz (0.1.0 … 1.1.0)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Cómo funciona (flujo de `lib/auth_jwt_go.rb`)
|
|
31
|
+
|
|
32
|
+
1. La app host configura la gema en un initializer:
|
|
33
|
+
```ruby
|
|
34
|
+
AuthJwtGo.configure do |config|
|
|
35
|
+
config.secret_key_api = 'SECRET_API' # requerido para authorized_app
|
|
36
|
+
config.secret_key_jwt = 'SECRET_JWT' # requerido para firmar/verificar JWT
|
|
37
|
+
config.algorithm = 'HS256' # opcional, default HS256
|
|
38
|
+
config.class_name_model = 'User' # opcional; si falta se usa AuthorizedUser
|
|
39
|
+
config.model_primary_key = 'id' # opcional, default 'id'
|
|
40
|
+
config.payload_primary_key = 'user_id' # opcional, default 'id'
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
2. `authorized_app` compara `request.headers['Api-Token']` con `secret_key_api`. Si no coincide responde 401.
|
|
44
|
+
3. `authorized_user` llama a `logged_in?` → `logged_in_user` → `decoded_token`:
|
|
45
|
+
- Toma `request.headers['Authorization']`, hace `split(' ')[1]` y decodifica con `JWT.decode`.
|
|
46
|
+
- Si `class_name_model` está configurado, busca el registro con `Model.find_by(model_primary_key => payload[payload_primary_key])`.
|
|
47
|
+
- Si no, construye un `AuthJwtGo::AuthorizedUser` con todos los campos del payload como `attr_accessor` (claves convertidas con `underscore`).
|
|
48
|
+
- El resultado queda en `@current_user`. Sin token válido responde 403; cualquier otra excepción responde 500.
|
|
49
|
+
4. `encode_token(payload)` devuelve `{ jwt: '<token>' }`.
|
|
50
|
+
5. `decoded_tenant(http_request)` devuelve un `AuthorizedUser` o un hash `{ message:, error: true }`. Ojo: no es consistente con el resto (mezcla objeto y hash como retorno).
|
|
51
|
+
6. Métodos de módulo para usar fuera de controladores (middlewares de Sidekiq, jobs, specs de las apps), sin que la app toque la gema `jwt`:
|
|
52
|
+
- `AuthJwtGo.encode(payload)` devuelve el token como string.
|
|
53
|
+
- `AuthJwtGo.decode(token)` devuelve el payload como hash con claves string. Acepta el token solo o con el prefijo `Bearer `.
|
|
54
|
+
- `AuthJwtGo.authorized_user_from(token)` devuelve un `AuthorizedUser`.
|
|
55
|
+
- Errores: `AuthJwtGo::DecodeError`, `AuthJwtGo::ExpiredSignature` y `AuthJwtGo::VerificationError`, alias de las clases de `jwt`. Todos los métodos de instancia usan estos internamente; si cambiás cómo se firma o verifica, hacelo acá.
|
|
56
|
+
|
|
57
|
+
## Dependencias implícitas (importante)
|
|
58
|
+
|
|
59
|
+
El gemspec declara `jwt` (`>= 2.2, < 4`) como dependencia runtime y `lib/auth_jwt_go.rb` la requiere, así que las apps no necesitan agregarla a su Gemfile. El resto se asume provisto por la app host:
|
|
60
|
+
|
|
61
|
+
- `ActiveSupport` para `present?`, `presence`, `classify`, `constantize`, `underscore`.
|
|
62
|
+
- `Rails` para los generadores (`Rails::Generators::Base`) y para `render`/`request` dentro de controladores.
|
|
63
|
+
|
|
64
|
+
Fuera de una app Rails, `lib/auth_jwt_go.rb` se puede cargar, pero los métodos del módulo no funcionan sin esos helpers. Si agregás una dependencia nueva, declarála en el gemspec con `spec.add_dependency`.
|
|
65
|
+
|
|
66
|
+
## Comandos
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
bin/setup # bundle install
|
|
70
|
+
bundle exec rspec # correr specs (rake por defecto también corre spec)
|
|
71
|
+
bundle exec rake spec
|
|
72
|
+
bin/console # IRB con la gema cargada
|
|
73
|
+
gem build auth_jwt_go.gemspec # genera auth_jwt_go-X.Y.Z.gem
|
|
74
|
+
gem push auth_jwt_go-X.Y.Z.gem # publicar en RubyGems (requiere credenciales)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Estado del entorno local
|
|
78
|
+
|
|
79
|
+
- `Gemfile.lock` está generado con **Bundler 2.7.2** sobre Ruby 3.4. Si ves el error `DidYouMean::SPELL_CHECKERS`, alguien volvió a generarlo con un Bundler viejo: regeneralo con `bundle _2.7.2_ install`.
|
|
80
|
+
- `.travis.yml` todavía apunta a Ruby 2.6.5 y no se usa.
|
|
81
|
+
- `lib/generators/auth_jwt_go/test_helper_generator.rb` usa `File.exists?`, que fue eliminado en Ruby 3.2. En Ruby ≥ 3.2 debe ser `File.exist?`.
|
|
82
|
+
|
|
83
|
+
## Tests
|
|
84
|
+
|
|
85
|
+
- Framework: RSpec 3 (`.rspec` carga `spec_helper` con formato documentation).
|
|
86
|
+
- `spec/auth_jwt_go_spec.rb` cubre `encode`, `decode`, `authorized_user_from`, `authorized_app`, `authorized_user`, `encode_token` y `decoded_tenant`.
|
|
87
|
+
- Los métodos de instancia se prueban incluyendo `AuthJwtGo` en una clase dummy que define `request` y `render`. `activesupport` está en el Gemfile solo para tests.
|
|
88
|
+
- La plantilla `templates/request_helpers.rb` muestra cómo las apps host arman tokens en sus specs (`encode_token(payload).dig(:jwt)` → `"Bearer #{jwt}"`).
|
|
89
|
+
|
|
90
|
+
## Convenciones
|
|
91
|
+
|
|
92
|
+
- **Código y README en inglés**; mensajes de commit históricamente en **español** (ej. `se agrega nueva version`).
|
|
93
|
+
- Ruby estándar: 2 espacios, `snake_case`, un módulo/clase por archivo bajo `lib/`.
|
|
94
|
+
- Versionado semántico en `lib/auth_jwt_go/version.rb`. Para publicar una versión: subir `VERSION`, `gem build`, `gem push`, commitear y taguear. Los `.gem` históricos están commiteados en la raíz; mantené esa práctica o limpiála de forma consciente, pero no borres los existentes sin consultar.
|
|
95
|
+
- Los tags existentes (`0.1.1-fix-message-error`, `fix-obj-auth`) vienen de ramas git-flow terminadas, no son tags de versión limpios. Hay ramas remotas `develop`, `development` y `feature/agregar-token-tenant`; `master` es la rama principal.
|
|
96
|
+
- Mantené compatibilidad con `required_ruby_version >= 2.3.0` salvo que se decida explícitamente subirla.
|
|
97
|
+
|
|
98
|
+
## Puntos sensibles de seguridad
|
|
99
|
+
|
|
100
|
+
- `authorized_app` compara el token de app con `eql?`; no es una comparación en tiempo constante. Si se refactoriza, usar `ActiveSupport::SecurityUtils.secure_compare`.
|
|
101
|
+
- `decoded_token` acepta el algoritmo configurado; nunca permitir `none` ni dejar que el algoritmo venga del token.
|
|
102
|
+
- `secret_key_api` y `secret_key_jwt` deben salir de variables de entorno en la app host, nunca hardcodeadas en el initializer.
|
|
103
|
+
|
|
104
|
+
## Bugs conocidos / deuda técnica
|
|
105
|
+
|
|
106
|
+
- `authorized_user` responde 403 cuando no hay token válido (semánticamente debería ser 401).
|
|
107
|
+
- `File.exists?` en el generador de test helper (ver arriba).
|
|
108
|
+
|
|
109
|
+
## Cómo trabajar en este repo
|
|
110
|
+
|
|
111
|
+
1. Leé `lib/auth_jwt_go.rb` completo antes de tocar la lógica; es un solo archivo de ~90 líneas y todo pasa por ahí.
|
|
112
|
+
2. Cualquier cambio de comportamiento público (headers, códigos HTTP, forma de los retornos) rompe apps que consumen la gema: documentalo en el README y subí la versión acorde a semver.
|
|
113
|
+
3. Cualquier cambio en `lib/` va acompañado de specs en `spec/auth_jwt_go_spec.rb`.
|
|
114
|
+
4. No publiques en RubyGems ni hagas push de tags sin confirmación explícita del dueño del repo. El proceso completo de release está en `docs/releasing.md`.
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
@AGENTS.md
|
|
4
|
+
|
|
5
|
+
## Notas para Claude Code
|
|
6
|
+
|
|
7
|
+
- Respondé en **español** al usuario; el código, comentarios y README se mantienen en **inglés**.
|
|
8
|
+
- Este repo es una **gema Ruby para Rails**, no un proyecto Go. No busques `go.mod` ni asumas tooling de Go por el nombre.
|
|
9
|
+
- Antes de editar `lib/auth_jwt_go.rb`, leé el archivo completo: toda la lógica de autenticación vive ahí y los cambios afectan a las apps que consumen la gema.
|
|
10
|
+
- Corré los specs con `bundle exec rspec`. La suite debe quedar en verde después de cada cambio.
|
|
11
|
+
- Publicar en RubyGems (`gem push`), crear tags o hacer push a `master` requiere confirmación explícita. Hay skills `git-main-deploy` y `git-sync-main` disponibles para el flujo de ramas y tags; usalas en vez de improvisar comandos.
|
|
12
|
+
- Al subir versión: editar `lib/auth_jwt_go/version.rb`, actualizar el ejemplo de versión en `README.md` si corresponde, y mencionar el cambio en el mensaje de commit.
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,46 +1,84 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
auth_jwt_go (
|
|
4
|
+
auth_jwt_go (1.1.0)
|
|
5
|
+
jwt (>= 2.2, < 4)
|
|
5
6
|
|
|
6
7
|
GEM
|
|
7
8
|
remote: https://rubygems.org/
|
|
8
9
|
specs:
|
|
9
|
-
|
|
10
|
+
activesupport (8.1.4)
|
|
11
|
+
base64
|
|
12
|
+
bigdecimal
|
|
13
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
14
|
+
connection_pool (>= 2.2.5)
|
|
15
|
+
drb
|
|
16
|
+
i18n (>= 1.6, < 2)
|
|
17
|
+
json
|
|
18
|
+
logger (>= 1.4.2)
|
|
19
|
+
minitest (>= 5.1)
|
|
20
|
+
securerandom (>= 0.3)
|
|
21
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
22
|
+
uri (>= 0.13.1)
|
|
23
|
+
base64 (0.3.0)
|
|
24
|
+
bigdecimal (4.1.3)
|
|
25
|
+
byebug (13.0.0)
|
|
26
|
+
reline (>= 0.6.0)
|
|
10
27
|
coderay (1.1.3)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
28
|
+
concurrent-ruby (1.3.8)
|
|
29
|
+
connection_pool (3.0.2)
|
|
30
|
+
diff-lcs (1.6.2)
|
|
31
|
+
drb (2.2.3)
|
|
32
|
+
i18n (1.15.2)
|
|
33
|
+
concurrent-ruby (~> 1.0)
|
|
34
|
+
io-console (0.9.4)
|
|
35
|
+
json (3.1.0)
|
|
36
|
+
jwt (3.3.0)
|
|
37
|
+
base64
|
|
38
|
+
logger (1.7.0)
|
|
39
|
+
method_source (1.1.0)
|
|
40
|
+
minitest (6.0.6)
|
|
41
|
+
drb (~> 2.0)
|
|
42
|
+
prism (~> 1.5)
|
|
43
|
+
prism (1.9.0)
|
|
44
|
+
pry (0.16.0)
|
|
15
45
|
coderay (~> 1.1)
|
|
16
46
|
method_source (~> 1.0)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
47
|
+
reline (>= 0.6.0)
|
|
48
|
+
pry-byebug (3.12.0)
|
|
49
|
+
byebug (~> 13.0)
|
|
50
|
+
pry (>= 0.13, < 0.17)
|
|
20
51
|
rake (12.3.3)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
rspec-
|
|
25
|
-
|
|
26
|
-
rspec-
|
|
27
|
-
rspec-
|
|
52
|
+
reline (0.7.0)
|
|
53
|
+
io-console (~> 0.5)
|
|
54
|
+
rspec (3.13.2)
|
|
55
|
+
rspec-core (~> 3.13.0)
|
|
56
|
+
rspec-expectations (~> 3.13.0)
|
|
57
|
+
rspec-mocks (~> 3.13.0)
|
|
58
|
+
rspec-core (3.13.6)
|
|
59
|
+
rspec-support (~> 3.13.0)
|
|
60
|
+
rspec-expectations (3.13.5)
|
|
28
61
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
29
|
-
rspec-support (~> 3.
|
|
30
|
-
rspec-mocks (3.
|
|
62
|
+
rspec-support (~> 3.13.0)
|
|
63
|
+
rspec-mocks (3.13.8)
|
|
31
64
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
32
|
-
rspec-support (~> 3.
|
|
33
|
-
rspec-support (3.
|
|
65
|
+
rspec-support (~> 3.13.0)
|
|
66
|
+
rspec-support (3.13.7)
|
|
67
|
+
securerandom (0.4.1)
|
|
68
|
+
tzinfo (2.0.6)
|
|
69
|
+
concurrent-ruby (~> 1.0)
|
|
70
|
+
uri (1.1.2)
|
|
34
71
|
|
|
35
72
|
PLATFORMS
|
|
36
73
|
ruby
|
|
74
|
+
x86_64-linux
|
|
37
75
|
|
|
38
76
|
DEPENDENCIES
|
|
77
|
+
activesupport
|
|
39
78
|
auth_jwt_go!
|
|
40
|
-
jwt
|
|
41
79
|
pry-byebug
|
|
42
80
|
rake (~> 12.0)
|
|
43
81
|
rspec (~> 3.0)
|
|
44
82
|
|
|
45
83
|
BUNDLED WITH
|
|
46
|
-
2.
|
|
84
|
+
2.7.2
|
data/README.md
CHANGED
|
@@ -7,9 +7,10 @@ This gem allows you to make identifications for your microservices and create th
|
|
|
7
7
|
Add this line to your application's Gemfile:
|
|
8
8
|
|
|
9
9
|
```ruby
|
|
10
|
-
gem '
|
|
11
|
-
gem 'auth_jwt_go', '~> 1.0.0'
|
|
10
|
+
gem 'auth_jwt_go', '~> 1.0'
|
|
12
11
|
```
|
|
12
|
+
The `jwt` gem is installed automatically as a dependency, you don't need to add it to your Gemfile.
|
|
13
|
+
|
|
13
14
|
And then execute:
|
|
14
15
|
|
|
15
16
|
$ bundle install
|
|
@@ -55,6 +56,31 @@ Or install it yourself as:
|
|
|
55
56
|
5- rspec add in rspec_rails
|
|
56
57
|
config.include RequestHelpers, type: :controller
|
|
57
58
|
|
|
59
|
+
## Encoding and decoding tokens outside controllers
|
|
60
|
+
|
|
61
|
+
The gem exposes module methods that use the configured `secret_key_jwt` and `algorithm`, so you never need to call the `jwt` gem directly (Sidekiq middlewares, jobs, services, specs):
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
token = AuthJwtGo.encode(user_id: user.id, exp: 1.day.from_now.to_i)
|
|
65
|
+
# => "eyJhbGciOiJIUzI1NiJ9..."
|
|
66
|
+
|
|
67
|
+
AuthJwtGo.decode(token) # => { "user_id" => 1, "exp" => 1700000000 }
|
|
68
|
+
AuthJwtGo.decode("Bearer #{token}") # the "Bearer " prefix is optional
|
|
69
|
+
|
|
70
|
+
user = AuthJwtGo.authorized_user_from(token)
|
|
71
|
+
user.user_id # => 1
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`decode` and `authorized_user_from` raise `AuthJwtGo::ExpiredSignature` for expired tokens, `AuthJwtGo::VerificationError` when the signature does not match, and `AuthJwtGo::DecodeError` for any other invalid or missing token. Both are subclasses of `DecodeError`, so rescuing `AuthJwtGo::DecodeError` catches all of them. They can also be used with `rescue_from`:
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
begin
|
|
78
|
+
Current.user = AuthJwtGo.authorized_user_from(job['current_jwt'])
|
|
79
|
+
rescue AuthJwtGo::DecodeError => e
|
|
80
|
+
Rails.logger.warn("Invalid JWT: #{e.message}")
|
|
81
|
+
end
|
|
82
|
+
```
|
|
83
|
+
|
|
58
84
|
## include helper current_user
|
|
59
85
|
|
|
60
86
|
## Contributing
|
data/auth_jwt_go.gemspec
CHANGED
|
@@ -15,9 +15,13 @@ Gem::Specification.new do |spec|
|
|
|
15
15
|
# Specify which files should be added to the gem when it is released.
|
|
16
16
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
17
17
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
18
|
-
`git ls-files -z`.split("\x0").reject
|
|
18
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
19
|
+
f.match(%r{^(test|spec|features|docs|bin|\.idea|\.ruby-lsp)/}) || f.end_with?('.gem')
|
|
20
|
+
end
|
|
19
21
|
end
|
|
20
22
|
spec.bindir = "exe"
|
|
21
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
22
24
|
spec.require_paths = ["lib"]
|
|
25
|
+
|
|
26
|
+
spec.add_dependency "jwt", ">= 2.2", "< 4"
|
|
23
27
|
end
|
data/lib/auth_jwt_go/version.rb
CHANGED
data/lib/auth_jwt_go.rb
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
require 'jwt'
|
|
1
2
|
require 'auth_jwt_go/version'
|
|
2
3
|
require 'auth_jwt_go/authorized_user'
|
|
3
4
|
|
|
4
5
|
module AuthJwtGo
|
|
6
|
+
DEFAULT_ALGORITHM = 'HS256'
|
|
7
|
+
|
|
8
|
+
# Re-exported so host apps can rescue them without referencing the jwt gem.
|
|
9
|
+
# ExpiredSignature and VerificationError inherit from DecodeError, so rescuing DecodeError catches all.
|
|
10
|
+
DecodeError = JWT::DecodeError
|
|
11
|
+
ExpiredSignature = JWT::ExpiredSignature
|
|
12
|
+
VerificationError = JWT::VerificationError
|
|
13
|
+
|
|
5
14
|
class << self
|
|
6
15
|
attr_accessor :secret_key_api,
|
|
7
16
|
:secret_key_jwt,
|
|
@@ -15,6 +24,27 @@ module AuthJwtGo
|
|
|
15
24
|
yield self
|
|
16
25
|
end
|
|
17
26
|
|
|
27
|
+
# Signs a payload with the configured secret and algorithm.
|
|
28
|
+
# AuthJwtGo.encode(user_id: 1, exp: 1.day.from_now.to_i) # => "eyJhbGciOi..."
|
|
29
|
+
def self.encode(payload)
|
|
30
|
+
JWT.encode(payload, secret_key_jwt, algorithm || DEFAULT_ALGORITHM)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Verifies a token and returns its payload as a Hash with string keys.
|
|
34
|
+
# Accepts the raw token or the full header value ("Bearer <token>").
|
|
35
|
+
# Raises AuthJwtGo::ExpiredSignature or AuthJwtGo::DecodeError when invalid or missing.
|
|
36
|
+
# AuthJwtGo.decode("Bearer eyJhbGciOi...") # => { "user_id" => 1, ... }
|
|
37
|
+
def self.decode(token)
|
|
38
|
+
raw = token.is_a?(String) ? token.split(' ').last : token
|
|
39
|
+
JWT.decode(raw, secret_key_jwt, true, { algorithm: algorithm || DEFAULT_ALGORITHM })[0]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Same as decode, but wraps the payload in an AuthorizedUser.
|
|
43
|
+
# AuthJwtGo.authorized_user_from(job['current_jwt']).enterprise
|
|
44
|
+
def self.authorized_user_from(token)
|
|
45
|
+
AuthorizedUser.new(decode(token))
|
|
46
|
+
end
|
|
47
|
+
|
|
18
48
|
def authorized_user
|
|
19
49
|
render json: { message: 'The user has not token active' }, status: 403 unless logged_in?
|
|
20
50
|
rescue StandardError => e
|
|
@@ -29,19 +59,16 @@ module AuthJwtGo
|
|
|
29
59
|
|
|
30
60
|
def decoded_tenant(http_request)
|
|
31
61
|
return { message: 'The jwt can not decode!!!!', error: true } unless http_request.env["HTTP_AUTHORIZATION"]
|
|
32
|
-
|
|
33
|
-
decode = JWT.decode(token, AuthJwtGo::secret_key_jwt, true, { algorithm: AuthJwtGo::algorithm || 'HS256'} )
|
|
34
|
-
return { message: 'The jwt can not decode!!!!', error: true } unless decode
|
|
35
|
-
AuthJwtGo::AuthorizedUser.new(decode[0])
|
|
36
|
-
rescue JWT::DecodeError => e
|
|
37
|
-
{ message: "JWT::DecodeError => #{e.to_s}", error: true }
|
|
62
|
+
AuthJwtGo.authorized_user_from(bearer_token(http_request.env["HTTP_AUTHORIZATION"]))
|
|
38
63
|
rescue JWT::ExpiredSignature => e
|
|
39
64
|
{ message: "JWT::ExpiredSignature => #{e.to_s}", error: true }
|
|
65
|
+
rescue JWT::DecodeError => e
|
|
66
|
+
{ message: "JWT::DecodeError => #{e.to_s}", error: true }
|
|
40
67
|
end
|
|
41
68
|
|
|
42
69
|
def encode_token(payload)
|
|
43
70
|
return { message: 'The payload is not present'} unless payload.present?
|
|
44
|
-
{jwt:
|
|
71
|
+
{ jwt: AuthJwtGo.encode(payload) }
|
|
45
72
|
end
|
|
46
73
|
|
|
47
74
|
private
|
|
@@ -51,28 +78,32 @@ module AuthJwtGo
|
|
|
51
78
|
end
|
|
52
79
|
|
|
53
80
|
def logged_in_user
|
|
54
|
-
|
|
55
|
-
return unless
|
|
81
|
+
payload = decoded_token
|
|
82
|
+
return unless payload
|
|
56
83
|
|
|
57
84
|
default_field = 'id'
|
|
58
85
|
field_payload = AuthJwtGo::payload_primary_key.presence || default_field
|
|
59
86
|
field_model = AuthJwtGo::model_primary_key.presence || default_field
|
|
60
87
|
|
|
61
88
|
@current_user = if AuthJwtGo::class_name_model.present?
|
|
62
|
-
AuthJwtGo::class_name_model.classify.constantize.find_by(field_model =>
|
|
89
|
+
AuthJwtGo::class_name_model.classify.constantize.find_by(field_model => payload[field_payload])
|
|
63
90
|
else
|
|
64
|
-
AuthJwtGo::AuthorizedUser.new(
|
|
91
|
+
AuthJwtGo::AuthorizedUser.new(payload)
|
|
65
92
|
end
|
|
66
93
|
end
|
|
67
94
|
|
|
68
95
|
def decoded_token
|
|
69
96
|
return unless auth_jwt.present?
|
|
70
|
-
|
|
71
|
-
JWT.decode(token, AuthJwtGo::secret_key_jwt, true, { algorithm: AuthJwtGo::algorithm || 'HS256'} )
|
|
97
|
+
AuthJwtGo.decode(bearer_token(auth_jwt))
|
|
72
98
|
rescue JWT::DecodeError
|
|
73
99
|
nil
|
|
74
100
|
end
|
|
75
101
|
|
|
102
|
+
# Controllers only accept the "Bearer <token>" format.
|
|
103
|
+
def bearer_token(header_value)
|
|
104
|
+
header_value.to_s.split(' ')[1]
|
|
105
|
+
end
|
|
106
|
+
|
|
76
107
|
# { Authorization: 'Bearer <token>' }
|
|
77
108
|
def auth_jwt
|
|
78
109
|
request.headers['Authorization']
|
metadata
CHANGED
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: auth_jwt_go
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- jonathan rojas
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: jwt
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.2'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '4'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '2.2'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '4'
|
|
13
32
|
description: this authenticates your api with jwt include current_user helper
|
|
14
33
|
email:
|
|
15
34
|
- jonathangrh.25@gmail.com
|
|
@@ -18,30 +37,16 @@ extensions: []
|
|
|
18
37
|
extra_rdoc_files: []
|
|
19
38
|
files:
|
|
20
39
|
- ".gitignore"
|
|
21
|
-
- ".idea/.gitignore"
|
|
22
|
-
- ".idea/.rakeTasks"
|
|
23
|
-
- ".idea/auth_jwt_go.iml"
|
|
24
|
-
- ".idea/misc.xml"
|
|
25
|
-
- ".idea/modules.xml"
|
|
26
|
-
- ".idea/vcs.xml"
|
|
27
40
|
- ".rakeTasks"
|
|
28
41
|
- ".rspec"
|
|
29
42
|
- ".travis.yml"
|
|
43
|
+
- AGENTS.md
|
|
44
|
+
- CLAUDE.md
|
|
30
45
|
- Gemfile
|
|
31
46
|
- Gemfile.lock
|
|
32
47
|
- README.md
|
|
33
48
|
- Rakefile
|
|
34
|
-
- auth_jwt_go-0.1.0.gem
|
|
35
|
-
- auth_jwt_go-0.1.1.gem
|
|
36
|
-
- auth_jwt_go-0.1.2.gem
|
|
37
|
-
- auth_jwt_go-0.1.3.gem
|
|
38
|
-
- auth_jwt_go-0.1.4.gem
|
|
39
|
-
- auth_jwt_go-1.0.0.gem
|
|
40
|
-
- auth_jwt_go-1.0.1.gem
|
|
41
|
-
- auth_jwt_go-1.0.2.gem
|
|
42
49
|
- auth_jwt_go.gemspec
|
|
43
|
-
- bin/console
|
|
44
|
-
- bin/setup
|
|
45
50
|
- lib/auth_jwt_go.rb
|
|
46
51
|
- lib/auth_jwt_go/authorized_user.rb
|
|
47
52
|
- lib/auth_jwt_go/version.rb
|
|
@@ -52,7 +57,6 @@ files:
|
|
|
52
57
|
homepage: https://github.com/remolacho/auth_jwt_go
|
|
53
58
|
licenses: []
|
|
54
59
|
metadata: {}
|
|
55
|
-
post_install_message:
|
|
56
60
|
rdoc_options: []
|
|
57
61
|
require_paths:
|
|
58
62
|
- lib
|
|
@@ -67,8 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
67
71
|
- !ruby/object:Gem::Version
|
|
68
72
|
version: '0'
|
|
69
73
|
requirements: []
|
|
70
|
-
rubygems_version: 3.
|
|
71
|
-
signing_key:
|
|
74
|
+
rubygems_version: 3.6.7
|
|
72
75
|
specification_version: 4
|
|
73
76
|
summary: Auth API with Jwt include current_user helper
|
|
74
77
|
test_files: []
|
data/.idea/.gitignore
DELETED
data/.idea/.rakeTasks
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<Settings><!--This file was automatically generated by Ruby plugin.
|
|
3
|
-
You are allowed to:
|
|
4
|
-
1. Remove rake task
|
|
5
|
-
2. Add existing rake tasks
|
|
6
|
-
To add existing rake tasks automatically delete this file and reload the project.
|
|
7
|
-
--><RakeGroup description="" fullCmd="" taksId="rake" /></Settings>
|
data/.idea/auth_jwt_go.iml
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<module type="RUBY_MODULE" version="4">
|
|
3
|
-
<component name="ModuleRunConfigurationManager">
|
|
4
|
-
<shared />
|
|
5
|
-
</component>
|
|
6
|
-
<component name="NewModuleRootManager">
|
|
7
|
-
<content url="file://$MODULE_DIR$">
|
|
8
|
-
<sourceFolder url="file://$MODULE_DIR$/features" isTestSource="true" />
|
|
9
|
-
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
|
|
10
|
-
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
|
11
|
-
</content>
|
|
12
|
-
<orderEntry type="inheritedJdk" />
|
|
13
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
14
|
-
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.16.2, RVM: ruby-2.3.7) [gem]" level="application" />
|
|
15
|
-
<orderEntry type="library" scope="PROVIDED" name="jwt (v2.2.1, RVM: ruby-2.3.7) [gem]" level="application" />
|
|
16
|
-
<orderEntry type="library" scope="PROVIDED" name="method_source (v1.0.0, RVM: ruby-2.3.7) [gem]" level="application" />
|
|
17
|
-
</component>
|
|
18
|
-
</module>
|
data/.idea/misc.xml
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project version="4">
|
|
3
|
-
<component name="JavaScriptSettings">
|
|
4
|
-
<option name="languageLevel" value="ES6" />
|
|
5
|
-
</component>
|
|
6
|
-
<component name="ProjectRootManager" version="2" project-jdk-name="RVM: ruby-2.3.7" project-jdk-type="RUBY_SDK" />
|
|
7
|
-
</project>
|
data/.idea/modules.xml
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project version="4">
|
|
3
|
-
<component name="ProjectModuleManager">
|
|
4
|
-
<modules>
|
|
5
|
-
<module fileurl="file://$PROJECT_DIR$/.idea/auth_jwt_go.iml" filepath="$PROJECT_DIR$/.idea/auth_jwt_go.iml" />
|
|
6
|
-
</modules>
|
|
7
|
-
</component>
|
|
8
|
-
</project>
|
data/.idea/vcs.xml
DELETED
data/auth_jwt_go-0.1.0.gem
DELETED
|
Binary file
|
data/auth_jwt_go-0.1.1.gem
DELETED
|
Binary file
|
data/auth_jwt_go-0.1.2.gem
DELETED
|
Binary file
|
data/auth_jwt_go-0.1.3.gem
DELETED
|
Binary file
|
data/auth_jwt_go-0.1.4.gem
DELETED
|
Binary file
|
data/auth_jwt_go-1.0.0.gem
DELETED
|
Binary file
|
data/auth_jwt_go-1.0.1.gem
DELETED
|
Binary file
|
data/auth_jwt_go-1.0.2.gem
DELETED
|
Binary file
|
data/bin/console
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require "bundler/setup"
|
|
4
|
-
require "auth_jwt_go"
|
|
5
|
-
|
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
-
|
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
-
# require "pry"
|
|
11
|
-
# Pry.start
|
|
12
|
-
|
|
13
|
-
require "irb"
|
|
14
|
-
IRB.start(__FILE__)
|