Securely authenticate user requests
def login(conn, %{"username" => username, "password" => password}) do
user = Repo.get_by(User, username: username)
if user && Bcrypt.checkpw(password, user.password_hash) do
{:ok, token, _claims} = BasicAuthToken.encode_and_sign(user.username)
conn
|> put_resp_header("authorization", "Basic #{token}")
|> send_resp(:ok, "Logged in")
else
send_resp(conn, :unauthorized, "Incorrect username or password")
end
end
In the insecure code example, the server uses Basic Authentication, where the user credentials are Base64-encoded but not encrypted, and transmitted over the network. This can be easily decoded and allows an attacker to intercept the user's credentials.
def login(conn, %{"username" => username, "password" => password}) do
user = Repo.get_by(User, username: username)
if user && Bcrypt.checkpw(password, user.password_hash) do
{:ok, jwt, _full_claims} = Guardian.encode_and_sign(user, :token)
conn
|> put_resp_header("authorization", "Bearer #{jwt}")
|> send_resp(:ok, "Logged in")
else
send_resp(conn, :unauthorized, "Incorrect username or password")
end
end
In the secure code example, the server uses Bearer Authentication with a hashed token. The server generates a JWT token for the authenticated user and returns it in the Authorization header. This ensures the user's sensitive credentials are not transmitted over the network.