implement auth login with a JWT cookie
This commit is contained in:
parent
b5a71c87ad
commit
84bffc5f72
6 changed files with 86 additions and 6 deletions
|
@ -8,7 +8,10 @@ Login
|
||||||
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
||||||
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
<img class="mx-auto h-12 w-auto" src="https://nixin.distrilab.eu/logo-nixin.svg" alt="NixiN">
|
<img class="mx-auto h-12 w-auto" src="https://nixin.distrilab.eu/logo-nixin.svg" alt="NixiN">
|
||||||
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">Index</h2>
|
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
|
||||||
|
Index
|
||||||
|
</h2>
|
||||||
|
hello user {{user.name}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -34,7 +34,7 @@ Login
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
<form class="space-y-6" action="#" method="POST">
|
<form class="space-y-6" action="/login" method="POST">
|
||||||
<div>
|
<div>
|
||||||
<label for="email" class="block text-sm font-medium leading-6 text-gray-900">Email address</label>
|
<label for="email" class="block text-sm font-medium leading-6 text-gray-900">Email address</label>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Login
|
||||||
|
{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
||||||
|
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
|
<img class="mx-auto h-12 w-auto" src="https://nixin.distrilab.eu/logo-nixin.svg" alt="NixiN">
|
||||||
|
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
|
||||||
|
Register a new account
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
|
@ -146,3 +146,6 @@ auth:
|
||||||
secret: jECGaGSsMtQmKyYyGuk7
|
secret: jECGaGSsMtQmKyYyGuk7
|
||||||
# Token expiration time in seconds
|
# Token expiration time in seconds
|
||||||
expiration: 604800 # 7 days
|
expiration: 604800 # 7 days
|
||||||
|
location:
|
||||||
|
from: Cookie
|
||||||
|
name: token
|
||||||
|
|
|
@ -2,8 +2,18 @@
|
||||||
#![allow(clippy::unnecessary_struct_initialization)]
|
#![allow(clippy::unnecessary_struct_initialization)]
|
||||||
#![allow(clippy::unused_async)]
|
#![allow(clippy::unused_async)]
|
||||||
use loco_rs::prelude::*;
|
use loco_rs::prelude::*;
|
||||||
use axum::debug_handler;
|
|
||||||
use axum::{extract::State, Json};
|
use axum::{
|
||||||
|
debug_handler,
|
||||||
|
extract::State,
|
||||||
|
extract::Query,
|
||||||
|
response::{IntoResponse, Redirect},
|
||||||
|
http::StatusCode,
|
||||||
|
Json,
|
||||||
|
Form};
|
||||||
|
use axum_extra::extract::cookie::{CookieJar, Cookie};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use loco_rs::{
|
use loco_rs::{
|
||||||
app::AppContext,
|
app::AppContext,
|
||||||
controller::middleware,
|
controller::middleware,
|
||||||
|
@ -11,7 +21,10 @@ use loco_rs::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
models::users,
|
models::{
|
||||||
|
users,
|
||||||
|
//users::{LoginParams, RegisterParams},
|
||||||
|
},
|
||||||
views,
|
views,
|
||||||
controllers::middleware::auth_no_error,
|
controllers::middleware::auth_no_error,
|
||||||
};
|
};
|
||||||
|
@ -36,8 +49,52 @@ pub async fn home(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct LoginParams {
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub password: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a user login and returns a token
|
||||||
|
#[debug_handler]
|
||||||
|
pub async fn login(
|
||||||
|
auth: auth_no_error::JWTWithUserOpt<users::Model>,
|
||||||
|
//ViewEngine(v): ViewEngine<TeraView>,
|
||||||
|
State(ctx): State<AppContext>,
|
||||||
|
jar: CookieJar,
|
||||||
|
Form(params): Form<LoginParams>) -> Result<(CookieJar, Redirect), StatusCode> {
|
||||||
|
println!("Auth: {:?}",auth);
|
||||||
|
println!("Form parameters: {:?}",params);
|
||||||
|
println!("Cookie jar: {:?}",jar);
|
||||||
|
|
||||||
|
match params {
|
||||||
|
LoginParams{email: Some(email), password: Some(password)} => {
|
||||||
|
let user = users::Model::find_by_email(&ctx.db, &email).await
|
||||||
|
.or_else(|_| Err(StatusCode::UNAUTHORIZED))?;
|
||||||
|
let valid = user.verify_password(&password);
|
||||||
|
if !valid {
|
||||||
|
return Err(StatusCode::UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
let jwt_secret = ctx.config.get_jwt_config()
|
||||||
|
.or_else(|_| Err(StatusCode::UNAUTHORIZED))?;
|
||||||
|
let token = user
|
||||||
|
.generate_jwt(&jwt_secret.secret, &jwt_secret.expiration)
|
||||||
|
.or_else(|_| Err(StatusCode::UNAUTHORIZED))?;
|
||||||
|
Ok((
|
||||||
|
// the updated jar must be returned for the changes
|
||||||
|
// to be included in the response
|
||||||
|
jar.add(Cookie::new("token", token)),
|
||||||
|
Redirect::to("/"),))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(StatusCode::UNAUTHORIZED)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn routes() -> Routes {
|
pub fn routes() -> Routes {
|
||||||
Routes::new()
|
Routes::new()
|
||||||
//.prefix("homes")
|
//.prefix("homes")
|
||||||
.add("/", get(home))
|
.add("/", get(home))
|
||||||
|
.add("/login", post(login))
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,6 @@ pub fn login(v: &impl ViewRenderer) -> Result<Response> {
|
||||||
///
|
///
|
||||||
/// When there is an issue with rendering the view.
|
/// When there is an issue with rendering the view.
|
||||||
pub fn index(v: &impl ViewRenderer, user: &users::Model) -> Result<Response> {
|
pub fn index(v: &impl ViewRenderer, user: &users::Model) -> Result<Response> {
|
||||||
format::render().view(v, "server/show.html", data!({"user": user}))
|
format::render().view(v, "home/index.html", data!({"user": user}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue