Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class AuthController {
AuthFollowUpType.FullAuth,
-> runInEdt {
UiTelemetry.click(project, "amazonq_chatAuthenticate")
requestCredentialsForQ(project, connectionInitiatedFromQChatPanel = true)
requestCredentialsForQ(project, connectionInitiatedFromQChatPanel = true, isReauth = false)
}

AuthFollowUpType.ReAuth,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class SignInToQAction : SignInToQActionBase(message("q.sign.in")) {
UiTelemetry.click(project, "auth_start_Q")

if (!isQWebviewsAvailable()) {
requestCredentialsForQ(project)
requestCredentialsForQ(project, isReauth = false)
} else {
ToolWindowManager.getInstance(project).getToolWindow(AmazonQToolWindowFactory.WINDOW_ID)?.show()
}
Expand All @@ -42,7 +42,7 @@ abstract class SignInToQActionBase(actionName: String) : DumbAwareAction(actionN
reauthConnectionIfNeeded(project, it, isReAuth = true)
} ?: run {
runInEdt {
if (requestCredentialsForQ(project)) {
if (requestCredentialsForQ(project, isReauth = false)) {
if (!openMeetQPage(project)) {
return@runInEdt
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -810,50 +810,6 @@
"type": "authType"
}
]
},
{
"name": "auth_addConnection",
"description": "Captures the result of adding a new connection in the 'Add New Connection' workflow",
"metadata": [
{
"type": "attempts",
"required": false
},
{
"type": "credentialSourceId"
},
{
"type": "featureId",
"required": false
},
{
"type": "invalidInputFields",
"required": false
},
{
"type": "isAggregated",
"required": false
},
{
"type": "reason",
"required": false
},
{
"type": "result"
},
{
"type": "source",
"required": false
},
{
"type": "credentialStartUrl",
"required": false
},
{
"type": "isReAuth",
"required": false
}
]
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fun requestCredentialsForCodeWhisperer(
),
isFirstInstance: Boolean = false,
connectionInitiatedFromExplorer: Boolean = false,
isReauth: Boolean = false
): Boolean {
val authenticationDialog = SetupAuthenticationDialog(
project,
Expand Down Expand Up @@ -87,7 +88,8 @@ fun requestCredentialsForCodeWhisperer(
credentialSourceId = authenticationDialog.authType,
isAggregated = true,
attempts = authenticationDialog.attempts + 1,
result = Result.Succeeded
result = Result.Succeeded,
isReAuth = isReauth
)
AuthTelemetry.addedConnections(
project,
Expand All @@ -108,6 +110,7 @@ fun requestCredentialsForCodeWhisperer(
isAggregated = false,
attempts = authenticationDialog.attempts + 1,
result = Result.Cancelled,
isReAuth = isReauth
)
}
return isAuthenticationSuccessful
Expand All @@ -123,6 +126,7 @@ fun requestCredentialsForQ(
isFirstInstance: Boolean = false,
connectionInitiatedFromExplorer: Boolean = false,
connectionInitiatedFromQChatPanel: Boolean = false,
isReauth: Boolean
): Boolean {
// try to scope upgrade if we have a codewhisperer connection
val codeWhispererConnection = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(CodeWhispererConnection.getInstance())
Expand Down Expand Up @@ -194,7 +198,8 @@ fun requestCredentialsForQ(
credentialSourceId = authenticationDialog.authType,
isAggregated = true,
attempts = authenticationDialog.attempts + 1,
result = Result.Succeeded
result = Result.Succeeded,
isReAuth = isReauth
)
AuthTelemetry.addedConnections(
project,
Expand All @@ -215,6 +220,7 @@ fun requestCredentialsForQ(
isAggregated = false,
attempts = authenticationDialog.attempts + 1,
result = Result.Cancelled,
isReAuth = isReauth
)
}
return isAuthenticationSuccessful
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ class SetupAuthenticationDialog(
isAggregated = false,
attempts = ++attempts,
result = Result.Failed,
reason = "ConnectionUnsuccessful"
reason = "ConnectionUnsuccessful",
isReAuth = false
)
} ?: return

Expand Down Expand Up @@ -339,7 +340,8 @@ class SetupAuthenticationDialog(
isAggregated = false,
attempts = ++attempts,
result = Result.Failed,
reason = "DuplicateProfileName"
reason = "DuplicateProfileName",
isReAuth = false
)
return
}
Expand All @@ -365,7 +367,8 @@ class SetupAuthenticationDialog(
isAggregated = false,
attempts = ++attempts,
result = Result.Failed,
reason = "InvalidCredentials"
reason = "InvalidCredentials",
isReAuth = false
)
return
}
Expand Down Expand Up @@ -438,7 +441,8 @@ class SetupAuthenticationDialog(
isAggregated = false,
attempts = ++attempts,
result = Result.Failed,
reason = errorType
reason = errorType,
isReAuth = false
)

LOG.error(e) { errorMessage }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ enum class SourceOfEntry {
FIRST_STARTUP,
Q,
AMAZONQ_CHAT_PANEL,
LOGIN_BROWSER,
UNKNOWN,
;
override fun toString(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_URL
import software.aws.toolkits.jetbrains.core.credentials.sso.PendingAuthorization
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.InteractiveBearerTokenProvider
import software.aws.toolkits.jetbrains.core.credentials.ssoErrorMessageFromException
import software.aws.toolkits.jetbrains.core.gettingstarted.editor.SourceOfEntry
import software.aws.toolkits.jetbrains.utils.pluginAwareExecuteOnPooledThread
import software.aws.toolkits.jetbrains.utils.pollFor
import software.aws.toolkits.resources.AwsCoreBundle
Expand Down Expand Up @@ -87,7 +88,7 @@ abstract class LoginBrowser(

private var browserOpenTimer: Timer? = null

private fun startBrowserOpenTimer(startUrl: String, ssoRegion: String) {
private fun startBrowserOpenTimer(startUrl: String, ssoRegion: String, scopes: List<String>) {
browserOpenTimer = Timer()
browserOpenTimer?.schedule(
object : TimerTask() {
Expand All @@ -103,7 +104,11 @@ abstract class LoginBrowser(
AuthTelemetry.addConnection(
result = Result.Failed,
reason = "Browser authentication idle for more than 15min",
credentialSourceId = if (startUrl == SONO_URL) CredentialSourceId.AwsId else CredentialSourceId.IamIdentityCenter
credentialSourceId = if (startUrl == SONO_URL) CredentialSourceId.AwsId else CredentialSourceId.IamIdentityCenter,
isAggregated = false,
source = SourceOfEntry.LOGIN_BROWSER.toString(),
featureId = getFeatureId(scopes),
isReAuth = isReAuth(scopes, startUrl)
)
stopAndClearBrowserOpenTimer()
}
Expand All @@ -121,7 +126,7 @@ abstract class LoginBrowser(
}

protected val onPendingToken: (InteractiveBearerTokenProvider) -> Unit = { provider ->
startBrowserOpenTimer(provider.startUrl, provider.region)
startBrowserOpenTimer(provider.startUrl, provider.region, provider.scopes)
projectCoroutineScope(project).launch {
val authorization = pollForAuthorization(provider)
if (authorization != null) {
Expand Down Expand Up @@ -180,6 +185,7 @@ abstract class LoginBrowser(

open fun loginBuilderId(scopes: List<String>) {
val isReauth = isReAuth(scopes, SONO_URL)
val featureId = getFeatureId(scopes)
val onError: (Exception) -> Unit = { e ->
stopAndClearBrowserOpenTimer()
isUserCancellation(e)
Expand All @@ -196,7 +202,10 @@ abstract class LoginBrowser(
result = Result.Failed,
credentialSourceId = CredentialSourceId.AwsId,
reason = e.message,
isReAuth = isReauth
isReAuth = isReauth,
featureId = featureId,
isAggregated = false,
source = SourceOfEntry.LOGIN_BROWSER.toString()
)
}
val onSuccess: () -> Unit = {
Expand All @@ -212,7 +221,10 @@ abstract class LoginBrowser(
AuthTelemetry.addConnection(
result = Result.Succeeded,
credentialSourceId = CredentialSourceId.AwsId,
isReAuth = isReauth
isReAuth = isReauth,
featureId = featureId,
isAggregated = true,
source = SourceOfEntry.LOGIN_BROWSER.toString()
)
}

Expand All @@ -239,7 +251,7 @@ abstract class LoginBrowser(
region: AwsRegion,
): Pair<(Exception) -> Unit, () -> Unit> {
val isReAuth = isReAuth(scopes, url)

val featureId = getFeatureId(scopes)
val onError: (Exception) -> Unit = { e ->
stopAndClearBrowserOpenTimer()
val message = ssoErrorMessageFromException(e)
Expand Down Expand Up @@ -269,6 +281,9 @@ abstract class LoginBrowser(
credentialSourceId = CredentialSourceId.IamIdentityCenter,
reason = message,
isReAuth = isReAuth,
featureId = featureId,
isAggregated = false,
source = SourceOfEntry.LOGIN_BROWSER.toString()
)
}
val onSuccess: () -> Unit = {
Expand All @@ -286,7 +301,10 @@ abstract class LoginBrowser(
project = null,
result = Result.Succeeded,
isReAuth = isReAuth,
credentialSourceId = CredentialSourceId.IamIdentityCenter
credentialSourceId = CredentialSourceId.IamIdentityCenter,
featureId = featureId,
isAggregated = true,
source = SourceOfEntry.LOGIN_BROWSER.toString()
)
}
return Pair(onError, onSuccess)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
package software.aws.toolkits.jetbrains.core.webview

import com.intellij.openapi.util.registry.Registry
import software.aws.toolkits.jetbrains.core.credentials.sono.CODECATALYST_SCOPES
import software.aws.toolkits.jetbrains.core.credentials.sono.Q_SCOPES
import software.aws.toolkits.telemetry.AuthType
import software.aws.toolkits.telemetry.FeatureId

fun getAuthType(region: String = "us-east-1"): AuthType {
val isCommercialRegion = !region.startsWith("us-gov") && !region.startsWith("us-iso") && !region.startsWith("cn")
Expand All @@ -14,3 +17,12 @@ fun getAuthType(region: String = "us-east-1"): AuthType {
return AuthType.DeviceCode
}
}

fun getFeatureId(scopes: List<String>): FeatureId =
if (scopes.intersect(Q_SCOPES.toSet()).isNotEmpty()) {
FeatureId.Q
} else if (scopes.intersect(CODECATALYST_SCOPES.toSet()).isNotEmpty()) {
FeatureId.Codecatalyst
} else {
FeatureId.AwsExplorer
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class GettingStartedOnStartup : StartupActivity {
featureId = FeatureId.Unknown,
credentialSourceId = CredentialSourceId.Unknown,
isAggregated = true,
result = Result.Succeeded
result = Result.Succeeded,
isReAuth = false
)
AuthTelemetry.addedConnections(
project,
Expand All @@ -66,7 +67,8 @@ class GettingStartedOnStartup : StartupActivity {
credentialSourceId = CredentialSourceId.Unknown,
isAggregated = false,
result = Result.Failed,
reason = "Error opening getting started panel"
reason = "Error opening getting started panel",
isReAuth = false
)
AuthTelemetry.addedConnections(
project,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ fun requestCredentialsForCodeCatalyst(
credentialSourceId = authenticationDialog.authType,
isAggregated = true,
attempts = authenticationDialog.attempts + 1,
result = Result.Succeeded
result = Result.Succeeded,
isReAuth = false
)
AuthTelemetry.addedConnections(
project,
Expand All @@ -110,6 +111,7 @@ fun requestCredentialsForCodeCatalyst(
isAggregated = false,
attempts = authenticationDialog.attempts + 1,
result = Result.Cancelled,
isReAuth = false
)
}
return isAuthenticationSuccessful
Expand Down Expand Up @@ -157,7 +159,8 @@ fun requestCredentialsForExplorer(
credentialSourceId = authenticationDialog.authType,
isAggregated = true,
attempts = authenticationDialog.attempts + 1,
result = Result.Succeeded
result = Result.Succeeded,
isReAuth = false
)
AuthTelemetry.addedConnections(
project,
Expand All @@ -178,6 +181,7 @@ fun requestCredentialsForExplorer(
isAggregated = false,
attempts = authenticationDialog.attempts + 1,
result = Result.Cancelled,
isReAuth = false
)
}
return isAuthSuccessful
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,8 @@ class GettingStartedPanel(
oldConnectionCount,
initialEnabledConnection,
isFirstInstance,
connectionInitiatedFromExplorer
connectionInitiatedFromExplorer,
isReauth = true
),
panelReauthenticationRequired
)
Expand Down
Loading