Skip to content

Commit 37fdc35

Browse files
committed
Allow to continue with no MFA serial.
1 parent a1ee990 commit 37fdc35

File tree

1 file changed

+59
-34
lines changed

1 file changed

+59
-34
lines changed

s3/src/main/java/ch/cyberduck/core/sts/STSAuthorizationService.java

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import ch.cyberduck.core.TemporaryAccessTokens;
2727
import ch.cyberduck.core.aws.CustomClientConfiguration;
2828
import ch.cyberduck.core.exception.BackgroundException;
29+
import ch.cyberduck.core.exception.LoginCanceledException;
2930
import ch.cyberduck.core.exception.LoginFailureException;
3031
import ch.cyberduck.core.preferences.HostPreferences;
3132
import ch.cyberduck.core.preferences.HostPreferencesFactory;
@@ -101,38 +102,57 @@ public String validate(final Credentials credentials) throws BackgroundException
101102
public TemporaryAccessTokens getSessionToken(final Credentials credentials) throws BackgroundException {
102103
final PreferencesReader settings = new ProxyPreferencesReader(bookmark, credentials);
103104
// The purpose of the sts:GetSessionToken operation is to authenticate the user using MFA.
104-
final GetSessionTokenRequest sessionTokenRequest = new GetSessionTokenRequest()
105+
final GetSessionTokenRequest request = new GetSessionTokenRequest()
105106
.withRequestCredentialsProvider(S3CredentialsStrategy.toCredentialsProvider(credentials));
106107
final String mfaArn = settings.getProperty(Profile.STS_MFA_ARN_PROPERTY_KEY);
107108
if(StringUtils.isNotBlank(mfaArn)) {
108109
log.debug("Found MFA ARN {} for {}", mfaArn, bookmark);
109-
sessionTokenRequest.setSerialNumber(mfaArn);
110-
log.debug("Prompt for MFA token code");
111-
final String tokenCode = prompt.prompt(
112-
bookmark, String.format("%s %s", LocaleFactory.localizedString("Multi-Factor Authentication", "S3"),
113-
mfaArn),
114-
LocaleFactory.localizedString("Provide additional login credentials", "Credentials"),
115-
new LoginOptions(bookmark.getProtocol())
116-
.password(true)
117-
.passwordPlaceholder(LocaleFactory.localizedString("MFA Authentication Code", "S3"))
118-
.keychain(false)
119-
).getPassword();
120-
sessionTokenRequest.setTokenCode(tokenCode);
121-
log.debug("Request {} from {}", sessionTokenRequest, service);
122-
try {
123-
final GetSessionTokenResult sessionTokenResult = service.getSessionToken(sessionTokenRequest);
124-
log.debug("Set credentials from {}", sessionTokenResult);
125-
return new TemporaryAccessTokens(
126-
sessionTokenResult.getCredentials().getAccessKeyId(),
127-
sessionTokenResult.getCredentials().getSecretAccessKey(),
128-
sessionTokenResult.getCredentials().getSessionToken(),
129-
sessionTokenResult.getCredentials().getExpiration().getTime());
130-
}
131-
catch(AWSSecurityTokenServiceException e) {
132-
throw new STSExceptionMappingService().map(e);
110+
request.setSerialNumber(mfaArn);
111+
}
112+
else {
113+
if(bookmark.getProtocol().isMultiFactorConfigurable()) {
114+
// When defined in connection profile but with empty value
115+
log.debug("Prompt for MFA ARN");
116+
try {
117+
final Credentials input = prompt.prompt(bookmark,
118+
LocaleFactory.localizedString("MFA Device Identifier", "S3"),
119+
LocaleFactory.localizedString("Provide additional login credentials", "Credentials"),
120+
new LoginOptions().icon(bookmark.getProtocol().disk()).password(false)
121+
.passwordPlaceholder(LocaleFactory.localizedString("Serial Number or Amazon Resource Name (ARN)", "S3")));
122+
if(input.isSaved()) {
123+
preferences.setProperty(Profile.STS_MFA_ARN_PROPERTY_KEY, input.getPassword());
124+
}
125+
request.setSerialNumber(input.getPassword());
126+
}
127+
catch(LoginCanceledException e) {
128+
log.warn("Canceled MFA ARN input for {}", bookmark);
129+
}
133130
}
134131
}
135-
return TemporaryAccessTokens.EMPTY;
132+
log.debug("Prompt for MFA token code");
133+
final String tokenCode = prompt.prompt(
134+
bookmark, String.format("%s %s", LocaleFactory.localizedString("Multi-Factor Authentication", "S3"),
135+
mfaArn),
136+
LocaleFactory.localizedString("Provide additional login credentials", "Credentials"),
137+
new LoginOptions(bookmark.getProtocol())
138+
.password(true)
139+
.passwordPlaceholder(LocaleFactory.localizedString("MFA Authentication Code", "S3"))
140+
.keychain(false)
141+
).getPassword();
142+
request.setTokenCode(tokenCode);
143+
log.debug("Request {} from {}", request, service);
144+
try {
145+
final GetSessionTokenResult result = service.getSessionToken(request);
146+
log.debug("Set credentials from {}", result);
147+
return new TemporaryAccessTokens(
148+
result.getCredentials().getAccessKeyId(),
149+
result.getCredentials().getSecretAccessKey(),
150+
result.getCredentials().getSessionToken(),
151+
result.getCredentials().getExpiration().getTime());
152+
}
153+
catch(AWSSecurityTokenServiceException e) {
154+
throw new STSExceptionMappingService().map(e);
155+
}
136156
}
137157

138158
/**
@@ -181,15 +201,20 @@ public TemporaryAccessTokens assumeRole(final Credentials credentials) throws Ba
181201
if(StringUtils.EMPTY.equals(mfaArn)) {
182202
// When defined in connection profile but with empty value
183203
log.debug("Prompt for MFA ARN");
184-
final Credentials input = prompt.prompt(bookmark,
185-
LocaleFactory.localizedString("MFA Device Identifier", "S3"),
186-
LocaleFactory.localizedString("Provide additional login credentials", "Credentials"),
187-
new LoginOptions().icon(bookmark.getProtocol().disk()).password(false)
188-
.passwordPlaceholder(LocaleFactory.localizedString("Serial Number or Amazon Resource Name (ARN)", "S3")));
189-
if(input.isSaved()) {
190-
preferences.setProperty(Profile.STS_MFA_ARN_PROPERTY_KEY, input.getPassword());
204+
try {
205+
final Credentials input = prompt.prompt(bookmark,
206+
LocaleFactory.localizedString("MFA Device Identifier", "S3"),
207+
LocaleFactory.localizedString("Provide additional login credentials", "Credentials"),
208+
new LoginOptions().icon(bookmark.getProtocol().disk()).password(false)
209+
.passwordPlaceholder(LocaleFactory.localizedString("Serial Number or Amazon Resource Name (ARN)", "S3")));
210+
if(input.isSaved()) {
211+
preferences.setProperty(Profile.STS_MFA_ARN_PROPERTY_KEY, input.getPassword());
212+
}
213+
request.setSerialNumber(input.getPassword());
214+
}
215+
catch(LoginCanceledException e) {
216+
log.warn("Canceled MFA ARN input for {}", bookmark);
191217
}
192-
request.setSerialNumber(input.getPassword());
193218
}
194219
}
195220
if(request.getSerialNumber() != null) {

0 commit comments

Comments
 (0)