Skip to content

Commit c43ce2c

Browse files
committed
login mvp
1 parent 4ce7ab9 commit c43ce2c

4 files changed

Lines changed: 102 additions & 40 deletions

File tree

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,77 @@
1-
use aws_sdk_cognitoidentityprovider::types::AuthFlowType;
1+
use anyhow::{Error, Result, anyhow};
2+
use aws_sdk_cognitoidentityprovider::{
3+
error::SdkError, operation::admin_initiate_auth::AdminInitiateAuthError, types::AuthFlowType,
4+
};
25
use axum_extra::extract::{CookieJar, Host};
36
use http::Method;
47
use openapi::{
58
apis::auth::{Auth, AuthLoginPostResponse},
6-
models::AuthLoginPostRequest,
9+
models::{AuthLoginPost200Response, AuthLoginPostRequest},
710
};
811

9-
use crate::api_impl::{api::ApiImpl, error::ApiError};
12+
use crate::api_impl::api::ApiImpl;
1013

1114
#[async_trait::async_trait]
12-
impl Auth<ApiError> for ApiImpl {
15+
impl Auth<Error> for ApiImpl {
1316
async fn auth_login_post(
1417
&self,
1518

1619
_method: &Method,
1720
_host: &Host,
1821
_cookies: &CookieJar,
19-
_body: &AuthLoginPostRequest,
20-
) -> Result<AuthLoginPostResponse, ApiError> {
21-
// self.cognito_client
22-
// .admin_initiate_auth()
23-
// .user_pool_id(self.cognito_user_pool_id.clone())
24-
// .client_id(self.cognito_client_id.clone())
25-
// .auth_flow(AuthFlowType::AdminUserPasswordAuth)
26-
// .send()
27-
// .await?;
28-
29-
todo!()
22+
body: &AuthLoginPostRequest,
23+
) -> Result<AuthLoginPostResponse> {
24+
let admin_initiate_auth_result = self
25+
.cognito_client
26+
.admin_initiate_auth()
27+
.user_pool_id(&self.cognito_user_pool_id)
28+
.client_id(&self.cognito_client_id)
29+
.auth_flow(AuthFlowType::AdminUserPasswordAuth)
30+
.auth_parameters("USERNAME", &body.email)
31+
.auth_parameters("PASSWORD", &body.password)
32+
.send()
33+
.await;
34+
35+
let admin_initiate_auth_output = match admin_initiate_auth_result {
36+
Ok(output) => output,
37+
Err(SdkError::ServiceError(err))
38+
if matches!(
39+
err.err(),
40+
AdminInitiateAuthError::UserNotFoundException { .. }
41+
| AdminInitiateAuthError::NotAuthorizedException { .. }
42+
) =>
43+
{
44+
return Ok(AuthLoginPostResponse::Status401_InvalidCredentials(
45+
"Invalid email or password".to_string(),
46+
));
47+
}
48+
Err(err) => {
49+
return Err(anyhow!(
50+
"Error during Cognito authentication. for user {:?}: {:?}",
51+
body.email,
52+
err
53+
));
54+
}
55+
};
56+
57+
let auth_result = admin_initiate_auth_output
58+
.authentication_result()
59+
.ok_or(anyhow!(
60+
"Authentication result missing from Cognito response"
61+
))?;
62+
63+
let token = auth_result
64+
.access_token()
65+
.map(|at| at.to_string())
66+
.ok_or(anyhow!("Access token missing from Cognito response"))?;
67+
68+
let user_id = auth_result
69+
.id_token()
70+
.map(|id| id.to_string())
71+
.ok_or(anyhow!("ID token missing from Cognito response"))?;
72+
73+
Ok(AuthLoginPostResponse::Status200_LoginSuccessful(
74+
AuthLoginPost200Response { token, user_id },
75+
))
3076
}
3177
}

app/backend/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod api_impl;
1111
#[tokio::main]
1212
async fn main() -> Result<()> {
1313
tracing_subscriber::fmt()
14+
.with_ansi(false)
1415
.with_max_level(tracing::Level::ERROR)
1516
.init();
1617

app/deployment/lib/deployment-stack.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,23 @@ export class HeartOfTheValleyStack extends cdk.Stack {
1515
deletionProtection: true,
1616
});
1717

18+
const adminUserPool = new cdk.aws_cognito.UserPool(
19+
this,
20+
"HeartOfValleyAdminUserPool",
21+
{
22+
selfSignUpEnabled: false,
23+
signInAliases: {
24+
email: true,
25+
},
26+
},
27+
);
28+
const cognitoClient = adminUserPool.addClient("AdminUserPoolClient", {
29+
disableOAuth: true,
30+
authFlows: {
31+
adminUserPassword: true,
32+
},
33+
});
34+
1835
const apiHandler = new cdk.aws_lambda.Function(
1936
this,
2037
"HeartOfValleyApiHandler",
@@ -44,11 +61,14 @@ export class HeartOfTheValleyStack extends cdk.Stack {
4461
],
4562
environment: {
4663
TABLE_NAME: table.tableName,
64+
COGNITO_USER_POOL_ID: adminUserPool.userPoolId,
65+
COGNITO_CLIENT_ID: cognitoClient.userPoolClientId,
4766
},
4867
},
4968
);
5069

5170
table.grantReadWriteData(apiHandler);
71+
adminUserPool.grant(apiHandler, "cognito-idp:AdminInitiateAuth");
5272

5373
const frontendBucket = new cdk.aws_s3.Bucket(
5474
this,
@@ -133,20 +153,6 @@ export class HeartOfTheValleyStack extends cdk.Stack {
133153
},
134154
});
135155

136-
const adminUserPool = new cdk.aws_cognito.UserPool(
137-
this,
138-
"HeartOfValleyAdminUserPool",
139-
{
140-
selfSignUpEnabled: false,
141-
signInAliases: {
142-
email: true,
143-
},
144-
},
145-
);
146-
adminUserPool.addClient("AdminUserPoolClient", {
147-
disableOAuth: true,
148-
});
149-
150156
new cdk.CfnOutput(this, "FrontendBucketName", {
151157
value: frontendBucket.bucketName,
152158
});

openapi-spec/paths/auth/login.yaml

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ post:
2222
- email
2323
- password
2424
responses:
25-
'200':
25+
"200":
2626
description: Login successful
2727
content:
2828
application/json:
@@ -32,14 +32,23 @@ post:
3232
token:
3333
type: string
3434
description: Authentication token
35-
user:
36-
type: object
37-
properties:
38-
id:
39-
type: string
40-
email:
41-
type: string
42-
'401':
35+
userId:
36+
type: string
37+
description: ID of the authenticated user
38+
required:
39+
- token
40+
- userId
41+
"400":
42+
description: Bad request
43+
content:
44+
text/plain:
45+
schema:
46+
type: string
47+
"401":
4348
description: Invalid credentials
44-
'400':
45-
description: Bad request
49+
content:
50+
text/plain:
51+
schema:
52+
type: string
53+
"500":
54+
description: Internal server error

0 commit comments

Comments
 (0)