Add supprt for new Rails 5.2 aes-256-gcm cookies
This commit is contained in:
parent
96adec81bd
commit
512647156e
|
@ -35,7 +35,7 @@ RUN apk add --no-cache tzdata
|
||||||
|
|
||||||
COPY --from=go-build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
COPY --from=go-build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||||
COPY --from=go-build /app/service .
|
COPY --from=go-build /app/service .
|
||||||
COPY --from=go-build /app/*.yml ./
|
COPY --from=go-build /app/config/*.yml ./
|
||||||
|
|
||||||
RUN chmod +x /app/service
|
RUN chmod +x /app/service
|
||||||
USER nobody
|
USER nobody
|
||||||
|
|
|
@ -2,7 +2,7 @@ title: Super Graph Development
|
||||||
host_port: 0.0.0.0:8080
|
host_port: 0.0.0.0:8080
|
||||||
web_ui: true
|
web_ui: true
|
||||||
debug_level: 1
|
debug_level: 1
|
||||||
enable_tracing: false
|
enable_tracing: true
|
||||||
|
|
||||||
# Throw a 401 on auth failure for queries that need auth
|
# Throw a 401 on auth failure for queries that need auth
|
||||||
# valid values: always, per_query, never
|
# valid values: always, per_query, never
|
||||||
|
@ -25,28 +25,40 @@ auth_fail_block: never
|
||||||
# sheep: sheep
|
# sheep: sheep
|
||||||
|
|
||||||
auth:
|
auth:
|
||||||
type: header
|
# Can be 'rails' or 'jwt'
|
||||||
|
type: rails
|
||||||
cookie: _app_session
|
cookie: _app_session
|
||||||
|
|
||||||
|
# Comment this out if you want to disable setting
|
||||||
|
# the user_id via a header. Good for testing
|
||||||
header: X-User-ID
|
header: X-User-ID
|
||||||
|
|
||||||
# rails_cookie:
|
rails:
|
||||||
# secret_key_base: caf335bfcfdb04e50db5bb0a4d67ab9...
|
# Rails version this is used for reading the
|
||||||
|
# various cookies formats.
|
||||||
|
version: 5.2
|
||||||
|
|
||||||
# rails_memcache:
|
# Found in 'Rails.application.config.secret_key_base'
|
||||||
# host: 127.0.0.1
|
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
|
||||||
|
|
||||||
# rails_redis:
|
# Remote cookie store. (memcache or redis)
|
||||||
# url: redis://127.0.0.1:6379
|
# url: redis://127.0.0.1:6379
|
||||||
# password: ""
|
# password: test
|
||||||
# max_idle: 80,
|
# max_idle: 80,
|
||||||
# max_active: 12000,
|
# max_active: 12000,
|
||||||
|
|
||||||
|
# In most cases you don't need these
|
||||||
|
# salt: "encrypted cookie"
|
||||||
|
# sign_salt: "signed encrypted cookie"
|
||||||
|
# auth_salt: "authenticated encrypted cookie"
|
||||||
|
|
||||||
# jwt:
|
# jwt:
|
||||||
# provider: auth0
|
# provider: auth0
|
||||||
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
||||||
# public_key_file: /secrets/public_key.pem
|
# public_key_file: /secrets/public_key.pem
|
||||||
# public_key_type: ecdsa #rsa
|
# public_key_type: ecdsa #rsa
|
||||||
|
|
||||||
|
|
||||||
database:
|
database:
|
||||||
type: postgres
|
type: postgres
|
||||||
host: db
|
host: db
|
||||||
|
@ -77,18 +89,24 @@ database:
|
||||||
|
|
||||||
fields:
|
fields:
|
||||||
- name: users
|
- name: users
|
||||||
|
# This filter will overwrite defaults.filter
|
||||||
filter: ["{ id: { eq: $user_id } }"]
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
- name: products
|
- name: products
|
||||||
|
# Multiple filters are AND'd together
|
||||||
filter: [
|
filter: [
|
||||||
"{ price: { gt: 0 } }",
|
"{ price: { gt: 0 } }",
|
||||||
"{ price: { lt: 8 } }"
|
"{ price: { lt: 8 } }"
|
||||||
]
|
]
|
||||||
|
|
||||||
- name: customers
|
- name: customers
|
||||||
|
# No filter is used for this field not
|
||||||
|
# even defaults.filter
|
||||||
filter: none
|
filter: none
|
||||||
|
|
||||||
- name: me
|
- # You can create new fields that have a
|
||||||
|
# real db table backing them
|
||||||
|
name: me
|
||||||
table: users
|
table: users
|
||||||
filter: ["{ id: { eq: $user_id } }"]
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
title: Super Graph Production
|
||||||
|
host_port: 0.0.0.0:8080
|
||||||
|
web_ui: false
|
||||||
|
debug_level: 0
|
||||||
|
enable_tracing: false
|
||||||
|
|
||||||
|
# Throw a 401 on auth failure for queries that need auth
|
||||||
|
# valid values: always, per_query, never
|
||||||
|
auth_fail_block: always
|
||||||
|
|
||||||
|
# Postgres related environment Variables
|
||||||
|
# SG_DATABASE_HOST
|
||||||
|
# SG_DATABASE_PORT
|
||||||
|
# SG_DATABASE_USER
|
||||||
|
# SG_DATABASE_PASSWORD
|
||||||
|
|
||||||
|
# Auth related environment Variables
|
||||||
|
# SG_AUTH_RAILS_COOKIE_SECRET_KEY_BASE
|
||||||
|
# SG_AUTH_RAILS_REDIS_URL
|
||||||
|
# SG_AUTH_RAILS_REDIS_PASSWORD
|
||||||
|
# SG_AUTH_JWT_PUBLIC_KEY_FILE
|
||||||
|
|
||||||
|
# inflections:
|
||||||
|
# person: people
|
||||||
|
# sheep: sheep
|
||||||
|
|
||||||
|
auth:
|
||||||
|
# Can be 'rails' or 'jwt'
|
||||||
|
type: rails
|
||||||
|
cookie: _app_session
|
||||||
|
|
||||||
|
# Comment this out if you want to disable setting
|
||||||
|
# the user_id via a header. Good for testing
|
||||||
|
header: X-User-ID
|
||||||
|
|
||||||
|
rails:
|
||||||
|
# Rails version this is used for reading the
|
||||||
|
# various cookies formats.
|
||||||
|
version: 5.2
|
||||||
|
|
||||||
|
# Found in 'Rails.application.config.secret_key_base'
|
||||||
|
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
|
||||||
|
|
||||||
|
# Remote cookie store. (memcache or redis)
|
||||||
|
# url: redis://127.0.0.1:6379
|
||||||
|
# password: test
|
||||||
|
# max_idle: 80,
|
||||||
|
# max_active: 12000,
|
||||||
|
|
||||||
|
# In most cases you don't need these
|
||||||
|
# salt: "encrypted cookie"
|
||||||
|
# sign_salt: "signed encrypted cookie"
|
||||||
|
# auth_salt: "authenticated encrypted cookie"
|
||||||
|
|
||||||
|
# jwt:
|
||||||
|
# provider: auth0
|
||||||
|
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
||||||
|
# public_key_file: /secrets/public_key.pem
|
||||||
|
# public_key_type: ecdsa #rsa
|
||||||
|
|
||||||
|
database:
|
||||||
|
type: postgres
|
||||||
|
host: db
|
||||||
|
port: 5432
|
||||||
|
dbname: app_development
|
||||||
|
user: postgres
|
||||||
|
password: ''
|
||||||
|
#pool_size: 10
|
||||||
|
#max_retries: 0
|
||||||
|
#log_level: "debug"
|
||||||
|
|
||||||
|
# Define variables here that you want to use in filters
|
||||||
|
variables:
|
||||||
|
account_id: "select account_id from users where id = $user_id"
|
||||||
|
|
||||||
|
# Define defaults to for the field key and values below
|
||||||
|
defaults:
|
||||||
|
filter: ["{ user_id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# Fields and table names that you wish to block
|
||||||
|
blacklist:
|
||||||
|
- ar_internal_metadata
|
||||||
|
- schema_migrations
|
||||||
|
- secret
|
||||||
|
- password
|
||||||
|
- encrypted
|
||||||
|
- token
|
||||||
|
|
||||||
|
fields:
|
||||||
|
- name: users
|
||||||
|
# This filter will overwrite defaults.filter
|
||||||
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
- name: products
|
||||||
|
# Multiple filters are AND'd together
|
||||||
|
filter: [
|
||||||
|
"{ price: { gt: 0 } }",
|
||||||
|
"{ price: { lt: 8 } }"
|
||||||
|
]
|
||||||
|
|
||||||
|
- name: customers
|
||||||
|
# No filter is used for this field not
|
||||||
|
# even defaults.filter
|
||||||
|
filter: none
|
||||||
|
|
||||||
|
- # You can create new fields that have a
|
||||||
|
# real db table backing them
|
||||||
|
name: me
|
||||||
|
table: users
|
||||||
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# - name: posts
|
||||||
|
# filter: ["{ account_id: { _eq: $account_id } }"]
|
|
@ -3,6 +3,13 @@ services:
|
||||||
db:
|
db:
|
||||||
image: postgres
|
image: postgres
|
||||||
|
|
||||||
|
# nginx:
|
||||||
|
# image: nginx:latest
|
||||||
|
# volumes:
|
||||||
|
# - ./example/nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
# ports:
|
||||||
|
# - 3001:3001
|
||||||
|
|
||||||
super_graph:
|
super_graph:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
|
@ -28,3 +35,4 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
- super_graph
|
- super_graph
|
||||||
|
# - nginx
|
|
@ -423,22 +423,33 @@ auth_fail_block: never
|
||||||
# sheep: sheep
|
# sheep: sheep
|
||||||
|
|
||||||
auth:
|
auth:
|
||||||
type: header
|
# Can be 'rails' or 'jwt'
|
||||||
|
type: rails
|
||||||
cookie: _app_session
|
cookie: _app_session
|
||||||
|
|
||||||
|
# Comment this out if you want to disable setting
|
||||||
|
# the user_id via a header. Good for testing
|
||||||
header: X-User-ID
|
header: X-User-ID
|
||||||
|
|
||||||
# rails_cookie:
|
rails:
|
||||||
# secret_key_base: caf335bfcfdb04e50db5bb0a4d67ab9...
|
# Rails version this is used for reading the
|
||||||
|
# various cookies formats.
|
||||||
|
version: 5.2
|
||||||
|
|
||||||
# rails_memcache:
|
# Found in 'Rails.application.config.secret_key_base'
|
||||||
# host: 127.0.0.1
|
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
|
||||||
|
|
||||||
# rails_redis:
|
# Remote cookie store. (memcache or redis)
|
||||||
# url: redis://127.0.0.1:6379
|
# url: redis://127.0.0.1:6379
|
||||||
# password: ""
|
# password: test
|
||||||
# max_idle: 80,
|
# max_idle: 80,
|
||||||
# max_active: 12000,
|
# max_active: 12000,
|
||||||
|
|
||||||
|
# In most cases you don't need these
|
||||||
|
# salt: "encrypted cookie"
|
||||||
|
# sign_salt: "signed encrypted cookie"
|
||||||
|
# auth_salt: "authenticated encrypted cookie"
|
||||||
|
|
||||||
# jwt:
|
# jwt:
|
||||||
# provider: auth0
|
# provider: auth0
|
||||||
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
||||||
|
@ -452,9 +463,9 @@ database:
|
||||||
dbname: app_development
|
dbname: app_development
|
||||||
user: postgres
|
user: postgres
|
||||||
password: ''
|
password: ''
|
||||||
#pool_size: 10
|
# pool_size: 10
|
||||||
#max_retries: 0
|
# max_retries: 0
|
||||||
#log_level: "debug"
|
# log_level: "debug"
|
||||||
|
|
||||||
# Define variables here that you want to use in filters
|
# Define variables here that you want to use in filters
|
||||||
variables:
|
variables:
|
||||||
|
|
|
@ -8,7 +8,7 @@ Devise.setup do |config|
|
||||||
# confirmation, reset password and unlock tokens in the database.
|
# confirmation, reset password and unlock tokens in the database.
|
||||||
# Devise will use the `secret_key_base` as its `secret_key`
|
# Devise will use the `secret_key_base` as its `secret_key`
|
||||||
# by default. You can change it below and use your own secret key.
|
# by default. You can change it below and use your own secret key.
|
||||||
# config.secret_key = 'da45f01cc03f113df2ac8788aab0833ff0ce6d3f2e298e964e0b35c7f63877588054a503106f0102d412987a45ed49e9a49697a6cf66da22f04ca6dafd24f76d'
|
# config.secret_key = ''
|
||||||
|
|
||||||
# ==> Controller configuration
|
# ==> Controller configuration
|
||||||
# Configure the parent class to the devise controllers.
|
# Configure the parent class to the devise controllers.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Rails.application.config.secret_key_base= '0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566'
|
|
@ -0,0 +1,25 @@
|
||||||
|
events { }
|
||||||
|
|
||||||
|
http {
|
||||||
|
server {
|
||||||
|
server_name localhost;
|
||||||
|
listen 3001;
|
||||||
|
|
||||||
|
location /api/v1/graphql {
|
||||||
|
proxy_pass http://super_graph:8080;
|
||||||
|
proxy_redirect off;
|
||||||
|
#rewrite ^/api/v1/graphql$ $1 break;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /super-graph {
|
||||||
|
proxy_pass http://super_graph:8080;
|
||||||
|
proxy_redirect off;
|
||||||
|
rewrite ^/super-graph/(.*)$ /$1 break;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://web:3000;
|
||||||
|
proxy_redirect off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
go.mod
2
go.mod
|
@ -1,6 +1,7 @@
|
||||||
module github.com/dosco/super-graph
|
module github.com/dosco/super-graph
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/Masterminds/semver v1.4.2
|
||||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3
|
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737
|
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
|
@ -13,6 +14,7 @@ require (
|
||||||
github.com/sirupsen/logrus v1.4.0
|
github.com/sirupsen/logrus v1.4.0
|
||||||
github.com/spf13/viper v1.3.1
|
github.com/spf13/viper v1.3.1
|
||||||
github.com/valyala/fasttemplate v1.0.1
|
github.com/valyala/fasttemplate v1.0.1
|
||||||
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
|
||||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a
|
||||||
mellium.im/sasl v0.2.1 // indirect
|
mellium.im/sasl v0.2.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1,5 +1,7 @@
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
|
||||||
|
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3 h1:+qz9Ga6l6lKw6fgvk5RMV5HQznSLvI8Zxajwdj4FhFg=
|
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3 h1:+qz9Ga6l6lKw6fgvk5RMV5HQznSLvI8Zxajwdj4FhFg=
|
||||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3/go.mod h1:FlkD11RtgMTYjVuBnb7cxoHmQGqvPpCsr2atC88nl/M=
|
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3/go.mod h1:FlkD11RtgMTYjVuBnb7cxoHmQGqvPpCsr2atC88nl/M=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
|
|
79
prod.yml
79
prod.yml
|
@ -1,79 +0,0 @@
|
||||||
title: Super Graph Production
|
|
||||||
host_port: 0.0.0.0:8080
|
|
||||||
web_ui: false
|
|
||||||
debug_level: 0
|
|
||||||
enable_tracing: false
|
|
||||||
|
|
||||||
# Throw a 401 on auth failure for queries that need auth
|
|
||||||
# valid values: always, per_query, never
|
|
||||||
auth_fail_block: always
|
|
||||||
|
|
||||||
# Postgres related environment Variables
|
|
||||||
# SG_DATABASE_HOST
|
|
||||||
# SG_DATABASE_PORT
|
|
||||||
# SG_DATABASE_USER
|
|
||||||
# SG_DATABASE_PASSWORD
|
|
||||||
|
|
||||||
# Auth related environment Variables
|
|
||||||
# SG_AUTH_RAILS_COOKIE_SECRET_KEY_BASE
|
|
||||||
# SG_AUTH_RAILS_REDIS_URL
|
|
||||||
# SG_AUTH_RAILS_REDIS_PASSWORD
|
|
||||||
# SG_AUTH_JWT_PUBLIC_KEY_FILE
|
|
||||||
|
|
||||||
# inflections:
|
|
||||||
# person: people
|
|
||||||
# sheep: sheep
|
|
||||||
|
|
||||||
auth:
|
|
||||||
type: cookie
|
|
||||||
cookie: _app_session
|
|
||||||
|
|
||||||
rails_cookie:
|
|
||||||
secret_key_base: caf335bfcfdb04e50db5bb0a4d67ab9...
|
|
||||||
|
|
||||||
# rails_memcache:
|
|
||||||
# host: 127.0.0.1
|
|
||||||
|
|
||||||
# rails_redis:
|
|
||||||
# url: redis://127.0.0.1:6379
|
|
||||||
# password: ""
|
|
||||||
# max_idle: 80,
|
|
||||||
# max_active: 12000,
|
|
||||||
|
|
||||||
# jwt:
|
|
||||||
# provider: auth0
|
|
||||||
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
|
||||||
# public_key_file: /secrets/public_key.pem
|
|
||||||
# public_key_type: ecdsa #rsa
|
|
||||||
|
|
||||||
database:
|
|
||||||
type: postgres
|
|
||||||
host: db
|
|
||||||
port: 5432
|
|
||||||
dbname: app_development
|
|
||||||
user: postgres
|
|
||||||
password: ''
|
|
||||||
#pool_size: 10
|
|
||||||
#max_retries: 0
|
|
||||||
#log_level: "debug"
|
|
||||||
|
|
||||||
# Define variables here that you want to use in filters
|
|
||||||
variables:
|
|
||||||
account_id: "select account_id from users where id = $user_id"
|
|
||||||
|
|
||||||
# Define defaults to for the field key and values below
|
|
||||||
defaults:
|
|
||||||
filter: ["{ id: { _eq: $user_id } }"]
|
|
||||||
|
|
||||||
# Fields and table names that you wish to block
|
|
||||||
blacklist:
|
|
||||||
- ar_internal_metadata
|
|
||||||
- schema_migrations
|
|
||||||
- secret
|
|
||||||
- password
|
|
||||||
- encrypted
|
|
||||||
- token
|
|
||||||
|
|
||||||
fields:
|
|
||||||
- name: users
|
|
||||||
filter: ["{ id: { _eq: $user_id } }"]
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
package rails
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Masterminds/semver"
|
||||||
|
"github.com/adjust/gorails/marshal"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
salt = "encrypted cookie"
|
||||||
|
signSalt = "signed encrypted cookie"
|
||||||
|
authSalt = "authenticated encrypted cookie"
|
||||||
|
railsCipher = "aes-256-cbc"
|
||||||
|
railsCipher52 = "aes-256-gcm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errSessionData = errors.New("error decoding session data")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Auth struct {
|
||||||
|
Cipher string
|
||||||
|
Secret string
|
||||||
|
Salt string
|
||||||
|
SignSalt string
|
||||||
|
AuthSalt string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuth(version, secret string) (*Auth, error) {
|
||||||
|
ra := &Auth{
|
||||||
|
Secret: secret,
|
||||||
|
Salt: salt,
|
||||||
|
SignSalt: signSalt,
|
||||||
|
AuthSalt: authSalt,
|
||||||
|
}
|
||||||
|
|
||||||
|
ver, err := semver.NewVersion(version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("rails auth: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gt52, err := semver.NewConstraint(">= 5.2")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("rails auth: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if gt52.Check(ver) {
|
||||||
|
ra.Cipher = railsCipher52
|
||||||
|
} else {
|
||||||
|
ra.Cipher = railsCipher
|
||||||
|
}
|
||||||
|
|
||||||
|
return ra, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ra *Auth) ParseCookie(cookie string) (userID string, err error) {
|
||||||
|
var dcookie []byte
|
||||||
|
|
||||||
|
switch ra.Cipher {
|
||||||
|
case railsCipher:
|
||||||
|
dcookie, err = parseCookie(cookie, ra.Secret, ra.Salt, ra.SignSalt)
|
||||||
|
|
||||||
|
case railsCipher52:
|
||||||
|
dcookie, err = parseCookie52(cookie, ra.Secret, ra.AuthSalt)
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("unknown rails cookie cipher '%s'", ra.Cipher)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if dcookie[0] != '{' {
|
||||||
|
userID, err = getUserId4(dcookie)
|
||||||
|
} else {
|
||||||
|
userID, err = getUserId(dcookie)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseCookie(cookie string) (string, error) {
|
||||||
|
if cookie[0] != '{' {
|
||||||
|
return getUserId4([]byte(cookie))
|
||||||
|
}
|
||||||
|
|
||||||
|
return getUserId([]byte(cookie))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserId(data []byte) (userID string, err error) {
|
||||||
|
var sessionData map[string]interface{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(data, &sessionData)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userKey, ok := sessionData["warden.user.user.key"]
|
||||||
|
if !ok {
|
||||||
|
err = errors.New("key 'warden.user.user.key' not found in session data")
|
||||||
|
}
|
||||||
|
|
||||||
|
items, ok := userKey.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
err = errSessionData
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(items) != 2 {
|
||||||
|
err = errSessionData
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uids, ok := items[0].([]interface{})
|
||||||
|
if !ok {
|
||||||
|
err = errSessionData
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uid, ok := uids[0].(float64)
|
||||||
|
if !ok {
|
||||||
|
err = errSessionData
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userID = fmt.Sprintf("%d", int64(uid))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserId4(data []byte) (userID string, err error) {
|
||||||
|
sessionData, err := marshal.CreateMarshalledObject(data).GetAsMap()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wardenData, ok := sessionData["warden.user.user.key"]
|
||||||
|
if !ok {
|
||||||
|
err = errSessionData
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wardenUserKey, err := wardenData.GetAsArray()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(wardenUserKey) < 1 {
|
||||||
|
err = errSessionData
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userData, err := wardenUserKey[0].GetAsArray()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(userData) < 1 {
|
||||||
|
err = errSessionData
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uid, err := userData[0].GetAsInteger()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userID = fmt.Sprintf("%d", uid)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
|
@ -1,15 +1,22 @@
|
||||||
package serv
|
package rails
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRailsEncryptedSession(t *testing.T) {
|
func TestRailsEncryptedSession1(t *testing.T) {
|
||||||
cookie := "dDdjMW5jYUNYaFpBT1BSdFgwQkk4ZWNlT214L1FnM0pyZzZ1d21nSnVTTm9zS0ljN000S1JmT3cxcTNtRld2Ny0tQUFBQUFBQUFBQUFBQUFBQUFBQUFBQT09--75d8323b0f0e41cf4d5aabee1b229b1be76b83b6"
|
cookie := "dDdjMW5jYUNYaFpBT1BSdFgwQkk4ZWNlT214L1FnM0pyZzZ1d21nSnVTTm9zS0ljN000S1JmT3cxcTNtRld2Ny0tQUFBQUFBQUFBQUFBQUFBQUFBQUFBQT09--75d8323b0f0e41cf4d5aabee1b229b1be76b83b6"
|
||||||
|
|
||||||
secret := "development_secret"
|
secret := "development_secret"
|
||||||
|
|
||||||
userID, err := railsAuth(cookie, secret)
|
ra := Auth{
|
||||||
|
Cipher: railsCipher,
|
||||||
|
Secret: secret,
|
||||||
|
Salt: salt,
|
||||||
|
SignSalt: signSalt,
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, err := ra.ParseCookie(cookie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -20,6 +27,29 @@ func TestRailsEncryptedSession(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRailsEncryptedSession52(t *testing.T) {
|
||||||
|
cookie :=
|
||||||
|
"fZy1lt%2FIuXh2cpQgy3wWjbvabh1AqJX%2Bt6qO4D95DOZIpDhMyK2HqPFeNoaBtrXCUa9%2BDQuvbs1GX6tuccEAp14QPLNhm0PPJS5U1pRHqPLWaqT%2BBPYP%2BY9bo677komm9CPuOCOqBKf7rv3%2F4ptLmVO7iefB%2FP2ZlkV1848Johv5q%2B5PGyMxII2BEQnBdS3Petw6lRu741Bquc8z9VofC3t4%2F%2BLxVz%2BvBbTg--VL0MorYITXB8Dj3W--0yr0sr6pRU%2FwlYMQ%2BpEifA%3D%3D"
|
||||||
|
|
||||||
|
secret := "0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566"
|
||||||
|
|
||||||
|
ra := Auth{
|
||||||
|
Cipher: railsCipher52,
|
||||||
|
Secret: secret,
|
||||||
|
AuthSalt: authSalt,
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, err := ra.ParseCookie(cookie)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if userID != "2" {
|
||||||
|
t.Errorf("Expecting userID 2 got %s", userID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRailsJsonSession(t *testing.T) {
|
func TestRailsJsonSession(t *testing.T) {
|
||||||
sessionData := `{"warden.user.user.key":[[1],"secret"]}`
|
sessionData := `{"warden.user.user.key":[[1],"secret"]}`
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package rails
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/base64"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/adjust/gorails/session"
|
||||||
|
"golang.org/x/crypto/pbkdf2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseCookie(cookie, secretKeyBase, salt, signSalt string) ([]byte, error) {
|
||||||
|
return session.DecryptSignedCookie(
|
||||||
|
cookie,
|
||||||
|
secretKeyBase,
|
||||||
|
salt,
|
||||||
|
signSalt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// {"session_id":"a71d6ffcd4ed5572ea2097f569eb95ef","warden.user.user.key":[[2],"$2a$11$q9Br7m4wJxQvF11hAHvTZO"],"_csrf_token":"HsYgrD2YBaWAabOYceN0hluNRnGuz49XiplmMPt43aY="}
|
||||||
|
|
||||||
|
func parseCookie52(cookie, secretKeyBase, authSalt string) ([]byte, error) {
|
||||||
|
ecookie, err := url.QueryUnescape(cookie)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
vectors := strings.Split(ecookie, "--")
|
||||||
|
|
||||||
|
body, err := base64.RawStdEncoding.DecodeString(vectors[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
iv, err := base64.RawStdEncoding.DecodeString(vectors[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tag, err := base64.StdEncoding.DecodeString(vectors[2])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
key := pbkdf2.Key([]byte(secretKeyBase), []byte(authSalt),
|
||||||
|
1000, 32, sha1.New)
|
||||||
|
|
||||||
|
c, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gcm, err := cipher.NewGCM(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gcm.Open(nil, iv, append(body, tag...), nil)
|
||||||
|
}
|
49
serv/auth.go
49
serv/auth.go
|
@ -2,62 +2,47 @@ package serv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
"strings"
|
||||||
|
|
||||||
const (
|
|
||||||
salt = "encrypted cookie"
|
|
||||||
signSalt = "signed encrypted cookie"
|
|
||||||
emptySecret = ""
|
|
||||||
authHeader = "Authorization"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
userIDProviderKey = struct{}{}
|
userIDProviderKey = struct{}{}
|
||||||
userIDKey = struct{}{}
|
userIDKey = struct{}{}
|
||||||
errSessionData = errors.New("error decoding session data")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func headerHandler(next http.HandlerFunc) http.HandlerFunc {
|
func headerAuth(r *http.Request, c *config) *http.Request {
|
||||||
fn := conf.Auth.Header
|
if len(c.Auth.Header) == 0 {
|
||||||
if len(fn) == 0 {
|
return nil
|
||||||
panic(errors.New("no auth.header defined"))
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
userID := r.Header.Get(fn)
|
|
||||||
if len(userID) == 0 {
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userID := r.Header.Get(c.Auth.Header)
|
||||||
|
if len(userID) != 0 {
|
||||||
ctx := context.WithValue(r.Context(), userIDKey, userID)
|
ctx := context.WithValue(r.Context(), userIDKey, userID)
|
||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
return r.WithContext(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func withAuth(next http.HandlerFunc) http.HandlerFunc {
|
func withAuth(next http.HandlerFunc) http.HandlerFunc {
|
||||||
at := conf.Auth.Type
|
at := conf.Auth.Type
|
||||||
|
ru := conf.Auth.Rails.URL
|
||||||
|
|
||||||
switch at {
|
switch at {
|
||||||
case "header":
|
case "rails":
|
||||||
return headerHandler(next)
|
if strings.HasPrefix(ru, "memcache:") {
|
||||||
|
|
||||||
case "rails_cookie":
|
|
||||||
return railsCookieHandler(next)
|
|
||||||
|
|
||||||
case "rails_memcache":
|
|
||||||
return railsMemcacheHandler(next)
|
return railsMemcacheHandler(next)
|
||||||
|
}
|
||||||
|
|
||||||
case "rails_redis":
|
if strings.HasPrefix(ru, "redis:") {
|
||||||
return railsRedisHandler(next)
|
return railsRedisHandler(next)
|
||||||
|
}
|
||||||
|
|
||||||
|
return railsCookieHandler(next)
|
||||||
|
|
||||||
case "jwt":
|
case "jwt":
|
||||||
return jwtHandler(next)
|
return jwtHandler(next)
|
||||||
|
|
||||||
default:
|
|
||||||
return next
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return next
|
return next
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
authHeader = "Authorization"
|
||||||
jwtBase int = iota
|
jwtBase int = iota
|
||||||
jwtAuth0
|
jwtAuth0
|
||||||
)
|
)
|
||||||
|
@ -57,6 +58,11 @@ func jwtHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var tok string
|
var tok string
|
||||||
|
|
||||||
|
if rn := headerAuth(r, conf); rn != nil {
|
||||||
|
next.ServeHTTP(w, rn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(cookie) != 0 {
|
if len(cookie) != 0 {
|
||||||
ck, err := r.Cookie(cookie)
|
ck, err := r.Cookie(cookie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,14 +2,14 @@ package serv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"github.com/adjust/gorails/marshal"
|
|
||||||
"github.com/adjust/gorails/session"
|
|
||||||
"github.com/bradfitz/gomemcache/memcache"
|
"github.com/bradfitz/gomemcache/memcache"
|
||||||
|
"github.com/dosco/super-graph/rails"
|
||||||
"github.com/garyburd/redigo/redis"
|
"github.com/garyburd/redigo/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,21 +19,20 @@ func railsRedisHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
panic(errors.New("no auth.cookie defined"))
|
panic(errors.New("no auth.cookie defined"))
|
||||||
}
|
}
|
||||||
|
|
||||||
authURL := conf.Auth.RailsRedis.URL
|
if len(conf.Auth.Rails.URL) == 0 {
|
||||||
if len(authURL) == 0 {
|
log.Fatal(errors.New("no auth.rails.url defined"))
|
||||||
panic(errors.New("no auth.rails_redis.url defined"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rp := &redis.Pool{
|
rp := &redis.Pool{
|
||||||
MaxIdle: conf.Auth.RailsRedis.MaxIdle,
|
MaxIdle: conf.Auth.Rails.MaxIdle,
|
||||||
MaxActive: conf.Auth.RailsRedis.MaxActive,
|
MaxActive: conf.Auth.Rails.MaxActive,
|
||||||
Dial: func() (redis.Conn, error) {
|
Dial: func() (redis.Conn, error) {
|
||||||
c, err := redis.DialURL(authURL)
|
c, err := redis.DialURL(conf.Auth.Rails.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pwd := conf.Auth.RailsRedis.Password
|
pwd := conf.Auth.Rails.Password
|
||||||
if len(pwd) != 0 {
|
if len(pwd) != 0 {
|
||||||
if _, err := c.Do("AUTH", pwd); err != nil {
|
if _, err := c.Do("AUTH", pwd); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -44,6 +43,11 @@ func railsRedisHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if rn := headerAuth(r, conf); rn != nil {
|
||||||
|
next.ServeHTTP(w, rn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ck, err := r.Cookie(cookie)
|
ck, err := r.Cookie(cookie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
|
@ -57,7 +61,7 @@ func railsRedisHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, err := railsAuth(string(sessionData), emptySecret)
|
userID, err := rails.ParseCookie(string(sessionData))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
|
@ -74,14 +78,23 @@ func railsMemcacheHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
panic(errors.New("no auth.cookie defined"))
|
panic(errors.New("no auth.cookie defined"))
|
||||||
}
|
}
|
||||||
|
|
||||||
host := conf.Auth.RailsMemcache.Host
|
if len(conf.Auth.Rails.URL) == 0 {
|
||||||
if len(host) == 0 {
|
log.Fatal(errors.New("no auth.rails.url defined"))
|
||||||
panic(errors.New("no auth.rails_memcache.host defined"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mc := memcache.New(host)
|
rURL, err := url.Parse(conf.Auth.Rails.URL)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mc := memcache.New(rURL.Host)
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if rn := headerAuth(r, conf); rn != nil {
|
||||||
|
next.ServeHTTP(w, rn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ck, err := r.Cookie(cookie)
|
ck, err := r.Cookie(cookie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
|
@ -95,7 +108,7 @@ func railsMemcacheHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, err := railsAuth(string(item.Value), emptySecret)
|
userID, err := rails.ParseCookie(string(item.Value))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
|
@ -112,11 +125,17 @@ func railsCookieHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
panic(errors.New("no auth.cookie defined"))
|
panic(errors.New("no auth.cookie defined"))
|
||||||
}
|
}
|
||||||
|
|
||||||
secret := conf.Auth.RailsCookie.SecretKeyBase
|
ra, err := railsAuth(conf)
|
||||||
if len(secret) == 0 {
|
if err != nil {
|
||||||
panic(errors.New("no auth.rails_cookie.secret_key_base defined"))
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if rn := headerAuth(r, conf); rn != nil {
|
||||||
|
next.ServeHTTP(w, rn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ck, err := r.Cookie(cookie)
|
ck, err := r.Cookie(cookie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
|
@ -124,7 +143,7 @@ func railsCookieHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, err := railsAuth(ck.Value, secret)
|
userID, err := ra.ParseCookie(ck.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
|
@ -136,98 +155,33 @@ func railsCookieHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func railsAuth(cookie, secret string) (userID string, err error) {
|
func railsAuth(c *config) (*rails.Auth, error) {
|
||||||
var dcookie []byte
|
secret := c.Auth.Rails.SecretKeyBase
|
||||||
|
if len(secret) == 0 {
|
||||||
|
return nil, errors.New("no auth.rails.secret_key_base defined")
|
||||||
|
}
|
||||||
|
|
||||||
dcookie, err = session.DecryptSignedCookie(cookie, secret, salt, signSalt)
|
version := c.Auth.Rails.Version
|
||||||
|
if len(version) == 0 {
|
||||||
|
return nil, errors.New("no auth.rails.version defined")
|
||||||
|
}
|
||||||
|
|
||||||
|
ra, err := rails.NewAuth(version, secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if dcookie[0] != '{' {
|
if len(c.Auth.Rails.Salt) != 0 {
|
||||||
userID, err = getUserId4(dcookie)
|
ra.Salt = c.Auth.Rails.Salt
|
||||||
} else {
|
|
||||||
userID, err = getUserId(dcookie)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
if len(conf.Auth.Rails.SignSalt) != 0 {
|
||||||
}
|
ra.SignSalt = c.Auth.Rails.SignSalt
|
||||||
|
}
|
||||||
func getUserId(data []byte) (userID string, err error) {
|
|
||||||
var sessionData map[string]interface{}
|
if len(conf.Auth.Rails.AuthSalt) != 0 {
|
||||||
|
ra.AuthSalt = c.Auth.Rails.AuthSalt
|
||||||
err = json.Unmarshal(data, &sessionData)
|
}
|
||||||
if err != nil {
|
|
||||||
return
|
return ra, nil
|
||||||
}
|
|
||||||
|
|
||||||
userKey, ok := sessionData["warden.user.user.key"]
|
|
||||||
if !ok {
|
|
||||||
err = errors.New("key 'warden.user.user.key' not found in session data")
|
|
||||||
}
|
|
||||||
|
|
||||||
items, ok := userKey.([]interface{})
|
|
||||||
if !ok {
|
|
||||||
err = errSessionData
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(items) != 2 {
|
|
||||||
err = errSessionData
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
uids, ok := items[0].([]interface{})
|
|
||||||
if !ok {
|
|
||||||
err = errSessionData
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
uid, ok := uids[0].(float64)
|
|
||||||
if !ok {
|
|
||||||
err = errSessionData
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userID = fmt.Sprintf("%d", int64(uid))
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserId4(data []byte) (userID string, err error) {
|
|
||||||
sessionData, err := marshal.CreateMarshalledObject(data).GetAsMap()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
wardenData, ok := sessionData["warden.user.user.key"]
|
|
||||||
if !ok {
|
|
||||||
err = errSessionData
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
wardenUserKey, err := wardenData.GetAsArray()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(wardenUserKey) < 1 {
|
|
||||||
err = errSessionData
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userData, err := wardenUserKey[0].GetAsArray()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(userData) < 1 {
|
|
||||||
err = errSessionData
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
uid, err := userData[0].GetAsInteger()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userID = fmt.Sprintf("%d", uid)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
15
serv/serv.go
15
serv/serv.go
|
@ -48,20 +48,17 @@ type config struct {
|
||||||
Cookie string
|
Cookie string
|
||||||
Header string
|
Header string
|
||||||
|
|
||||||
RailsCookie struct {
|
Rails struct {
|
||||||
|
Version string
|
||||||
SecretKeyBase string `mapstructure:"secret_key_base"`
|
SecretKeyBase string `mapstructure:"secret_key_base"`
|
||||||
} `mapstructure:"rails_cookie"`
|
|
||||||
|
|
||||||
RailsMemcache struct {
|
|
||||||
Host string
|
|
||||||
} `mapstructure:"rails_memcache"`
|
|
||||||
|
|
||||||
RailsRedis struct {
|
|
||||||
URL string
|
URL string
|
||||||
Password string
|
Password string
|
||||||
MaxIdle int `mapstructure:"max_idle"`
|
MaxIdle int `mapstructure:"max_idle"`
|
||||||
MaxActive int `mapstructure:"max_active"`
|
MaxActive int `mapstructure:"max_active"`
|
||||||
} `mapstructure:"rails_redis"`
|
Salt string
|
||||||
|
SignSalt string `mapstructure:"sign_salt"`
|
||||||
|
AuthSalt string `mapstructure:"auth_salt"`
|
||||||
|
}
|
||||||
|
|
||||||
JWT struct {
|
JWT struct {
|
||||||
Provider string
|
Provider string
|
||||||
|
|
Loading…
Reference in New Issue