Код: Выделить всё
NotAuthorizedException(message=Token is not from a supported provider of this identity pool.)
< /code>
Несмотря на то, что Google был добавлен в качестве поставщика идентификаторов в моем пуле идентификации Cognito с созданным я ClientId Web Application. Я создаю приложение с идентификатором клиента Android и создаю токен с идентификатором клиента веб -приложения. Идентификатор клиента веб -приложения определенно то, что я дал пул личности и присутствует как AUD в токене: < /p>
ID-token payload: {"iss":"https://accounts.google.com","azp":"391XXXXXX997-kbosaXXXXXXXXXXXXXXXXXXXefuvtc.apps.googleusercontent.com","aud":"391XXXXXX997-nvosialXXXXXXXXXXXXXXXXXXXXXXXXXXiv3a.apps.googleusercontent.com","sub":"101XXXXXXXXXXXXXX276","email":"f*********@gmail.com","email_verified":true,"name":"Nick Fusaro","picture":"https://lh3.googleusercontent.com/a/ACg8ocKyvcGJn03vo9cdzduSL3H0ByKww-IXjAO1AYzK9jpr6Z27agns=s96-c","given_name":"Nick","family_name":"Fusaro","iat":175XXXX172,"exp":1750615772} Вот логика моего приложения для аутентификации с помощью Google, получить токен и запросить учетные данные от cognito:
MainActivity:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
val apiKey = OpenAIConfig.apiKey
Log.d("MainActivity", "OpenAI key loaded: ${'$'}{!apiKey.isNullOrEmpty()}")
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestIdToken(BuildConfig.GOOGLE_WEB_CLIENT_ID)
.build()
val googleSignInClient = GoogleSignIn.getClient(this, gso)
setContent {
CYOATheme {
AppContent(googleSignInClient)
}
}
}
}
@Composable
fun AppContent(client: GoogleSignInClient) {
val loggedIn = remember { mutableStateOf(false) }
val error = remember { mutableStateOf(null) }
val account = remember { mutableStateOf(null) }
val navController = rememberNavController()
val repo = remember(account.value) {
val provider = CognitoCredentialsProvider(
BuildConfig.AWS_IDENTITY_POOL_ID,
account.value?.idToken
)
DynamoDbStoryRepository("Stories", provider)
}
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
if (task.isSuccessful) {
error.value = null
account.value = task.result
loggedIn.value = true
} else {
Log.e("MainActivity", "Google sign-in failed", task.exception)
error.value = task.exception?.localizedMessage ?: "Google sign-in failed"
}
}
if (loggedIn.value) {
NavHost(navController, startDestination = "list") {
composable("list") {
StoryListScreen(
repository = repo,
userId = account.value?.id ?: "default",
onSelect = { id -> navController.navigate("story/$id") }
)
}
composable("story/{id}") { backStackEntry ->
val sid = backStackEntry.arguments?.getString("id") ?: return@composable
MainScreen(
account.value,
onSignOut = {
client.signOut()
account.value = null
loggedIn.value = false
},
storyId = sid,
repository = repo,
userId = account.value?.id ?: "default"
)
}
}
} else {
LoginScreen(
onGoogleLogin = { launcher.launch(client.signInIntent) },
errorMessage = error.value
)
}
}
< /code>
cognitocredentialsprovider: < /p>
class CognitoCredentialsProvider(
private val identityPoolId: String,
private val googleIdToken: String? = null,
private val client: CognitoIdentityClient = CognitoIdentityClient {
region = BuildConfig.AWS_REGION
}
) : CredentialsProvider {
companion object {
private const val TAG = "CognitoCreds"
}
private var cached: AwsCredentials? = null
private var expiresAt: Instant? = null
/**
* Resolve credentials, refreshing from Cognito when necessary.
*/
suspend fun getCredentials(): AwsCredentials {
val now = Clock.System.now()
val creds = cached
val exp = expiresAt
if (creds != null && exp != null && now < exp) {
Log.d(TAG, "Returning cached credentials (expire at $exp)")
return creds
}
// Construct logins map (if any) and dump token details for debugging.
val logins = googleIdToken?.let { token ->
// Show only the first/last 10 chars so we don’t leak the whole JWT.
Log.d(TAG, "Using Google ID token: ${token.take(10)}…${token.takeLast(10)}")
// Optionally decode the token payload and print its claims:
decodeJwtPayload(token)?.also { payloadJson ->
Log.d(TAG, "ID-token payload: $payloadJson")
}
mapOf("accounts.google.com" to token)
}
Log.d(TAG, "Calling GetId for pool $identityPoolId with logins=$logins")
val idResp = client.getId(
GetIdRequest {
identityPoolId = this@CognitoCredentialsProvider.identityPoolId
logins?.let { this.logins = it }
}
)
Log.d(TAG, "Got identityId=${idResp.identityId}")
val credResp = client.getCredentialsForIdentity(
GetCredentialsForIdentityRequest {
identityId = idResp.identityId!!
logins?.let { this.logins = it }
}
)
val c = credResp.credentials!!
Log.d(TAG, "Received AWS creds expiring at ${c.expiration}")
val resolved = AwsCredentials(
accessKeyId = c.accessKeyId!!,
secretAccessKey = c.secretKey!!,
sessionToken = c.sessionToken
)
cached = resolved
expiresAt = c.expiration
return resolved
}
override suspend fun resolve(attributes: Attributes): AwsCredentials = getCredentials()
/**
* Decode a JWT without verifying its signature (debug builds only).
* Returns the payload JSON or null if the token is malformed.
*/
private fun decodeJwtPayload(jwt: String): String? = runCatching {
val parts = jwt.split('.')
if (parts.size < 2) return null
val payloadBytes = Base64.decode(parts[1], Base64.URL_SAFE or Base64.NO_PADDING or Base64.NO_WRAP)
payloadBytes.toString(UTF_8)
}.getOrNull()
}
< /code>
Конфигурация клиента Google
< /p>
Конфигурация пула идентификации
Подробнее здесь: https://stackoverflow.com/questions/796 ... gle-client
Мобильная версия