-
Notifications
You must be signed in to change notification settings - Fork 345
feat: Support Qv2 CLI social login #3060
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
949aff1
3104e90
234cb92
f0c0bbe
bbef143
14bed1a
8ce3a8f
af9e55a
8a6caf3
3b506ca
2f98df4
51c24c1
85f3be5
e6645f6
ec75414
3458ea4
39c4f9a
379e3bb
cfde581
ac1d692
13feeaa
5f140e1
ec2408f
aae5052
41bda6e
c602272
c378416
12d1ebb
e9ebd06
9a52674
1372a0e
59454d0
221acb5
3cd8474
02fe82e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,10 +3,21 @@ mod consts; | |
| pub mod pkce; | ||
| mod scope; | ||
|
|
||
| pub mod social; | ||
| use aws_sdk_ssooidc::config::{ | ||
| ConfigBag, | ||
| RuntimeComponents, | ||
| }; | ||
| use aws_sdk_ssooidc::error::SdkError; | ||
| use aws_sdk_ssooidc::operation::create_token::CreateTokenError; | ||
| use aws_sdk_ssooidc::operation::register_client::RegisterClientError; | ||
| use aws_sdk_ssooidc::operation::start_device_authorization::StartDeviceAuthorizationError; | ||
| use aws_smithy_runtime_api::client::identity::http::Token; | ||
| use aws_smithy_runtime_api::client::identity::{ | ||
| Identity, | ||
| IdentityFuture, | ||
| ResolveIdentity, | ||
| }; | ||
| pub use builder_id::{ | ||
| is_logged_in, | ||
| logout, | ||
|
|
@@ -15,6 +26,7 @@ pub use consts::START_URL; | |
| use thiserror::Error; | ||
|
|
||
| use crate::aws_common::SdkErrorDisplay; | ||
| use crate::database::Database; | ||
|
|
||
| #[derive(Debug, Error)] | ||
| pub enum AuthError { | ||
|
|
@@ -48,6 +60,19 @@ pub enum AuthError { | |
| OAuthCustomError(String), | ||
| #[error(transparent)] | ||
| DatabaseError(#[from] crate::database::DatabaseError), | ||
| #[error(transparent)] | ||
| Reqwest(#[from] reqwest::Error), | ||
| #[error("HTTP error: {0}")] | ||
| HttpStatus(reqwest::StatusCode), | ||
| // Social auth specific errors | ||
| #[error( | ||
| "Authentication failed: The identity provider denied access. Please ensure you grant all required permissions." | ||
| )] | ||
| SocialAuthProviderDeniedAccess, | ||
| #[error("Authentication failed: The identity provider reported an error: {0}")] | ||
| SocialAuthProviderFailure(String), | ||
| #[error("Invalid access code. Please check your invitation code and try again.")] | ||
| SocialInvalidInvitationCode, | ||
| } | ||
|
|
||
| impl From<aws_sdk_ssooidc::Error> for AuthError { | ||
|
|
@@ -73,3 +98,33 @@ impl From<SdkError<StartDeviceAuthorizationError>> for AuthError { | |
| Self::SdkStartDeviceAuthorization(Box::new(value)) | ||
| } | ||
| } | ||
| /// Unified bearer token resolver that tries both social and builder ID tokens | ||
| #[derive(Debug, Clone)] | ||
| pub struct UnifiedBearerResolver; | ||
|
|
||
| impl ResolveIdentity for UnifiedBearerResolver { | ||
| fn resolve_identity<'a>( | ||
| &'a self, | ||
| _runtime_components: &'a RuntimeComponents, | ||
| _config_bag: &'a ConfigBag, | ||
| ) -> IdentityFuture<'a> { | ||
| IdentityFuture::new_boxed(Box::pin(async { | ||
| let database = Database::new().await?; | ||
|
|
||
| if let Ok(Some(token)) = builder_id::BuilderIdToken::load(&database).await { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to check both all times? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| return Ok(Identity::new( | ||
| Token::new(token.access_token.0.clone(), Some(token.expires_at.into())), | ||
| Some(token.expires_at.into()), | ||
| )); | ||
| } | ||
|
|
||
| if let Ok(Some(token)) = social::SocialToken::load(&database).await { | ||
| return Ok(Identity::new( | ||
| Token::new(token.access_token.0.clone(), Some(token.expires_at.into())), | ||
| Some(token.expires_at.into()), | ||
| )); | ||
| } | ||
| Err(AuthError::NoToken.into()) | ||
| })) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.