Skip to content
This repository was archived by the owner on Aug 11, 2022. It is now read-only.

Commit 1bb6482

Browse files
author
Adrien Anselme
committed
Now checking password on login against db. Fixing bug in hashing js and changing db schema.
1 parent 6c0f460 commit 1bb6482

File tree

11 files changed

+81
-29
lines changed

11 files changed

+81
-29
lines changed

config/config.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@ config :phoenix, SbSso.Router,
1616
debug_errors: false,
1717
error_controller: SbSso.PageController
1818

19+
config :phoenix, :sso,
20+
payload_secret: "proutproutprout",
21+
redirect_url: "http://localhost:8080/session/sso_login?"
22+
1923
config :phoenix, :code_reloader,
2024
enabled: false
2125

2226
config :logger, :console,
2327
format: "$time $metadata[$level] $message\n",
2428
metadata: [:request_id]
2529

30+
config :bcrypt, [mechanism: :port, pool_size: 4]
31+
2632
# Import environment specific config. Note, this must remain at the bottom of
2733
# this file to properly merge your previous config entries.
2834
import_config "#{Mix.env}.exs"

mix.exs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ defmodule SbSso.Mixfile do
1313
def application do
1414
[
1515
mod: { SbSso, [] },
16-
applications: [:phoenix, :cowboy, :logger, :postgrex, :ecto, :erlsha2]
16+
applications: [:phoenix, :cowboy, :logger, :postgrex, :ecto, :erlsha2, :bcrypt]
1717
]
1818
end
1919

@@ -28,7 +28,8 @@ defmodule SbSso.Mixfile do
2828
{:cowboy, "~> 1.0.0"},
2929
{:postgrex, ">= 0.0.0"},
3030
{:ecto, "~> 0.2.0"},
31-
{:erlsha2, github: "vinoski/erlsha2"}
31+
{:erlsha2, github: "vinoski/erlsha2"},
32+
{:bcrypt, github: "smarkets/erlang-bcrypt"}
3233
]
3334
end
3435
end

mix.lock

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
%{"cowboy": {:package, "1.0.0"},
1+
%{"bcrypt": {:git, "git://github.com/smarkets/erlang-bcrypt.git", "14641089aa8ad8f9c17886c3ecf534868a282431", []},
2+
"cowboy": {:package, "1.0.0"},
23
"cowlib": {:package, "1.0.0"},
34
"decimal": {:package, "0.2.5"},
45
"ecto": {:package, "0.2.5"},

priv/repo/migrations/20140921163148_create_users.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ defmodule SbSso.Repo.Migrations.CreateUsers do
22
use Ecto.Migration
33

44
def up do
5-
["CREATE TABLE users(id serial primary key, email varchar(125), first_name varchar(50), last_name varchar(50), passwd_hash bytea, creation_datetime timestamp)",
6-
"INSERT INTO users(email, first_name, last_name, creation_datetime) VALUES ('foo@bar.com', 'Foo', 'Bar', current_timestamp)"
5+
["CREATE TABLE users(id serial primary key, email varchar(125) unique not null, first_name varchar(50), last_name varchar(50), username varchar(50), passwd_hash varchar(64) not null, salt varchar(64) not null, creation_datetime timestamp)",
6+
"INSERT INTO users(email, first_name, last_name, username, passwd_hash, salt, creation_datetime) VALUES ('foo@bar.com', 'Foo', 'Bar', 'foobar', '$2a$12$B.Ye..0ygflpgXsiQ8SOCOZsAd4GJEU2SDzHgMhLg5hLhLIP2BOc2', '$2a$12$B.Ye..0ygflpgXsiQ8SOCO', current_timestamp)"
77
]
88
end
99

priv/static/js/forms.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function formhash(form, password, email) {
66
p.type = "hidden"
77

88
// Call sjcl HMAC-SHA256 with salt on the password
9-
var key = sjcl.codec.utf8String.toBits(email + "springbeats.com");
9+
var key = sjcl.codec.utf8String.toBits(email.value + "springbeats.com");
1010
var out = (new sjcl.misc.hmac(key, sjcl.hash.sha256)).mac(password.value);
1111
p.value = sjcl.codec.hex.fromBits(out)
1212

web/controllers/crypto_helpers.ex

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ defmodule SbSso.CryptoHelpers do
77

88
def generate_salt(num_bytes) do
99
:crypto.bytes_to_integer(:crypto.strong_rand_bytes(num_bytes))
10+
|> :erlang.integer_to_list
11+
end
12+
13+
def generate_salt() do
14+
{:ok, salt} = :bcrypt.gen_salt(30)
15+
salt
16+
end
17+
18+
def hash(password, salt) do
19+
{:ok, h} = :bcrypt.hashpw(password, salt)
20+
h
1021
end
1122

1223
end

web/controllers/sso_controller.ex

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,68 @@
11
defmodule SbSso.SsoController do
22
use Phoenix.Controller
3-
alias SbSso.Router
4-
alias SbSso.Repo
53
alias SbSso.Queries
6-
alias SbSso.Users
7-
8-
@my_secret "proutproutprout"
9-
@discourse_url "http://localhost:8080/session/sso_login?"
4+
alias SbSso.CryptoHelpers
105

116
def show_login(conn, params) do
127
render conn, "login", params: params
138
end
149

10+
@doc """
11+
Given a map of parameters, check password and forward a signed payload
12+
to caller url.
13+
"""
1514
def do_login(conn, params) do
16-
sso = create_sso(params)
15+
sso = authenticate(params)
1716
payload = URI.encode_query(sso)
1817
|> :base64.encode_to_string
1918
|> to_string
2019
sig = payload
21-
|> sign(@my_secret)
22-
|> String.downcase
20+
|> CryptoHelpers.sign(get_secret())
2321
encoded_payload = URI.encode_www_form(payload)
24-
url = @discourse_url <> "sso=" <> encoded_payload <> "&sig=" <> sig
25-
IO.inspect(url)
22+
url = get_url <> "sso=" <> encoded_payload <> "&sig=" <> sig
2623
redirect conn, url
2724
end
2825

26+
@doc """
27+
Verify Payload signature and extract its content
28+
"""
2929
def parse(params) do
3030
sso = params["sso"]
31-
sig = String.upcase( params["sig"] )
31+
sig = params["sig"]
3232

33-
if sign(sso, get_secret()) !== sig do
33+
if CryptoHelpers.sign(sso, get_secret()) !== sig do
3434
raise RuntimeError, message: "Bad signature for payload"
3535
end
3636

3737
decoded = :base64.decode_to_string(sso) |> to_string
38-
IO.inspect(decoded)
39-
hquery = URI.decode_query(decoded)
38+
URI.decode_query(decoded)
4039
end
4140

42-
defp create_sso(params) do
43-
Map.merge(params, %{"name" => "sam", "external_id" => "hello123", "username" => "samsam"})
44-
end
41+
"""
42+
1.Retrieve user from DB
43+
2.Hash the (already client-hashed) password in params using salt in DB
44+
3.Compare this hash with the one stored in DB
45+
"""
46+
defp authenticate(params) do
47+
user = Queries.user_detail_from_email_query(params["email"])
48+
expected_hash = user.passwd_hash
49+
actual_hash = CryptoHelpers.hash(params["clienthash"], user.salt)
50+
51+
if actual_hash !== expected_hash do
52+
raise RuntimeError, message: "Username/password mismatch"
53+
end
4554

46-
defp sign(payload, sso_secret) do
47-
to_string( :hmac.hexlify(:hmac.hmac256(sso_secret, payload)) )
55+
# fill in the profile
56+
name = user.first_name <> " " <> user.last_name
57+
Map.merge(params, %{"name" => name, "external_id" => user.id, "username" => user.username})
4858
end
4959

5060
defp get_secret do
51-
@my_secret
61+
Application.get_env(:phoenix, :sso)[:payload_secret]
62+
end
63+
64+
defp get_url do
65+
Application.get_env(:phoenix, :sso)[:redirect_url]
5266
end
5367

5468
end

web/models/queries.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,12 @@ defmodule SbSso.Queries do
1717
select: user
1818
Repo.all(query) |> List.first
1919
end
20+
21+
def user_detail_from_email_query(email) do
22+
s_email = to_string(email)
23+
query = from user in Users,
24+
where: user.email == ^s_email,
25+
select: user
26+
Repo.all(query) |> List.first
27+
end
2028
end

web/models/users.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ defmodule SbSso.Users do
55
field :email, :string
66
field :first_name, :string
77
field :last_name, :string
8-
field :passwd_hash, :binary
8+
field :username, :string
9+
field :passwd_hash, :string
10+
field :salt, :string
911
field :creation_datetime, :datetime
1012
end
1113
end

web/templates/layout/application.html.eex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
1212
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
1313
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
14+
<script src="/js/sjcl.js"></script>
15+
<script src="/js/forms.js"></script>
1416
<link rel="stylesheet" href="/css/app.css">
1517
<link rel="stylesheet" href="/css/users.css">
1618
</head>

0 commit comments

Comments
 (0)