Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Authentication Service MKII release notes

## 0.8.1

* Agent, Developer, and Service tokens will now inherit the MFA status of the Login token used
to create them.
* Replaced the deprecated Globus `identities_set` directive with `identity_set`.
See https://docs.globus.org/api/auth/reference/#token-introspect

## 0.8.0

* BACKWARDS INCOMPATIBILITY: In flight login sessions when the server is upgraded will fail.
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/us/kbase/auth2/Version.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
public class Version {

/** The version of the KBase Auth2 service. */
public static final String VERSION = "0.8.0";
public static final String VERSION = "0.8.1";

}
33 changes: 28 additions & 5 deletions src/main/java/us/kbase/auth2/lib/Authentication.java
Original file line number Diff line number Diff line change
Expand Up @@ -892,8 +892,11 @@ public NewToken createToken(
throw new IllegalArgumentException("Cannot create a login token without logging in");
}
// check for disabled user for all token type targets as well
final AuthUser au = getUser(token,
new OpReqs("create {} token", tokenType.getDescription()).types(TokenType.LOGIN));
final UserAndToken uat = getUserAndToken(
token,
new OpReqs("create {} token", tokenType.getDescription()).types(TokenType.LOGIN)
);
final AuthUser au = uat.user;
if (!TokenType.AGENT.equals(tokenType)) {
final Role reqRole = TokenType.SERV.equals(tokenType) ?
Role.SERV_TOKEN : Role.DEV_TOKEN;
Expand All @@ -910,6 +913,7 @@ public NewToken createToken(
.withLifeTime(clock.instant(), life)
.withContext(tokenCtx)
.withTokenName(tokenName)
.withMFA(uat.token.getMFA())
.build(),
randGen.getToken()
);
Expand Down Expand Up @@ -953,8 +957,27 @@ private AuthUser getUser(
final IncomingToken token,
final OpReqs reqs)
throws AuthStorageException, InvalidTokenException, UnauthorizedException {
final StoredToken ht = getToken(token, reqs);
final AuthUser u = getUser(ht.getUserName());
return getUserAndToken(token, reqs).user;
}

private static class UserAndToken {
public final AuthUser user;
public final StoredToken token;

private UserAndToken(final AuthUser user, final StoredToken token) {
super();
this.user = user;
this.token = token;
}
}

// requires the user to have at least one of the required roles
private UserAndToken getUserAndToken(
final IncomingToken token,
final OpReqs reqs)
throws AuthStorageException, InvalidTokenException, UnauthorizedException {
final StoredToken st = getToken(token, reqs);
final AuthUser u = getUser(st.getUserName());
if (reqs.requiredRoles.size() > 0) {
final Set<Role> has = u.getRoles().stream().flatMap(r -> r.included().stream())
.collect(Collectors.toSet());
Expand All @@ -964,7 +987,7 @@ private AuthUser getUser(
throw new UnauthorizedException();
}
}
return u;
return new UserAndToken(u, st);
}

// assumes that the token has already been checked and is valid for this user.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ private Idents getPrimaryIdentity(
final MultivaluedMap<String, String> formParameters = new MultivaluedHashMap<>();
formParameters.add("token", accessToken);
if (!ignoreSecondaries) {
formParameters.add("include", "identities_set");
formParameters.add("include", "identity_set");
}

final Map<String, Object> m;
Expand Down Expand Up @@ -256,7 +256,7 @@ private Idents getPrimaryIdentity(
new RemoteIdentityID(NAME, id),
new RemoteIdentityDetails(username, name, email));
@SuppressWarnings("unchecked")
List<String> secids = (List<String>) m.get("identities_set");
List<String> secids = (List<String>) m.get("identity_set");
if (secids == null) {
secids = Collections.emptyList();
}
Expand Down
28 changes: 24 additions & 4 deletions src/test/java/us/kbase/test/auth2/lib/AuthenticationTokenTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import us.kbase.auth2.lib.exceptions.UnauthorizedException;
import us.kbase.auth2.lib.storage.AuthStorage;
import us.kbase.auth2.lib.token.IncomingToken;
import us.kbase.auth2.lib.token.MFAStatus;
import us.kbase.auth2.lib.token.NewToken;
import us.kbase.auth2.lib.token.StoredToken;
import us.kbase.auth2.lib.token.TokenName;
Expand Down Expand Up @@ -895,7 +896,9 @@ public void createAgentToken() throws Exception {
new UserName("foo"), UID, new DisplayName("bar"), Instant.now())
.build();

createToken(user, new HashMap<>(), 7 * 24 * 3600 * 1000L, TokenType.AGENT);
createToken(
user, new HashMap<>(), 7 * 24 * 3600 * 1000L, TokenType.AGENT, MFAStatus.NOT_USED
);
}

@Test
Expand All @@ -916,7 +919,7 @@ public void createDevToken() throws Exception {
.withEmailAddress(new EmailAddress("f@h.com"))
.withRole(Role.DEV_TOKEN).build();

createToken(user, new HashMap<>(), 90 * 24 * 3600 * 1000L, TokenType.DEV);
createToken(user, new HashMap<>(), 90 * 24 * 3600 * 1000L, TokenType.DEV, MFAStatus.USED);
}

@Test
Expand Down Expand Up @@ -948,7 +951,13 @@ public void createServToken() throws Exception {
.withEmailAddress(new EmailAddress("f@h.com"))
.withRole(Role.SERV_TOKEN).build();

createToken(user, new HashMap<>(), 100_000_000L * 24 * 3600 * 1000L, TokenType.SERV);
createToken(
user,
new HashMap<>(),
100_000_000L * 24 * 3600 * 1000L,
TokenType.SERV,
MFAStatus.USED
);
}

@Test
Expand Down Expand Up @@ -1051,6 +1060,15 @@ private void createToken(
final Map<TokenLifetimeType, Long> lifetimes,
final long expectedLifetime,
final TokenType tokenType) throws Exception {
createToken(user, lifetimes, expectedLifetime, tokenType, MFAStatus.UNKNOWN);
}

private void createToken(
final AuthUser user,
final Map<TokenLifetimeType, Long> lifetimes,
final long expectedLifetime,
final TokenType tokenType,
final MFAStatus mfa) throws Exception {
final TestMocks testauth = initTestMocks();
final AuthStorage storage = testauth.storageMock;
final Authentication auth = testauth.auth;
Expand All @@ -1064,7 +1082,7 @@ private void createToken(
final Instant time = Instant.ofEpochMilli(100000);
final StoredToken ht = StoredToken.getBuilder(
TokenType.LOGIN, UUID.randomUUID(), user.getUserName())
.withLifeTime(Instant.now(), Instant.now()).build();
.withLifeTime(Instant.now(), Instant.now()).withMFA(mfa).build();

when(storage.getToken(t.getHashedToken())).thenReturn(ht, (StoredToken) null);

Expand All @@ -1088,6 +1106,7 @@ private void createToken(
verify(storage).storeToken(StoredToken.getBuilder(tokenType, id, user.getUserName())
.withLifeTime(time, expiration)
.withTokenName(new TokenName("a name"))
.withMFA(mfa)
.withContext(TokenCreationContext.getBuilder()
.withNullableDevice("device").build()).build(),
"p40z9I2zpElkQqSkhbW6KG3jSgMRFr3ummqjSe7OzOc=");
Expand All @@ -1100,6 +1119,7 @@ private void createToken(
StoredToken.getBuilder(tokenType, id, user.getUserName())
.withLifeTime(time, time.plusMillis(expectedLifetime))
.withTokenName(new TokenName("a name"))
.withMFA(mfa)
.withContext(TokenCreationContext.getBuilder()
.withNullableDevice("device").build()).build(),
"this is a token");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public void returnsBadAudience() throws Exception {
.put("username", "aUsername")
.put("name", "fullname")
.put("email", "anEmail")
.put("identities_set",
.put("identity_set",
Arrays.asList("ident1", "anID", "ident2"))
.build()));
failGetIdentities(idp, authCode, "pixydust", false, new IdentityRetrievalException(
Expand Down Expand Up @@ -408,7 +408,7 @@ public void returnsBadSecondaryIdentityList() throws Exception {
.put("username", "aUsername")
.put("name", "fullname")
.put("email", "anEmail")
.put("identities_set",
.put("identity_set",
Arrays.asList("id1 ", "anID", "\nid2"))
.build()));

Expand Down Expand Up @@ -443,7 +443,7 @@ public void returnsBadResponseSecondaryID() throws Exception {
.put("username", "aUsername")
.put("name", "fullname")
.put("email", "anEmail")
.put("identities_set",
.put("identity_set",
Arrays.asList("id1 ", "anID"))
.build());

Expand Down Expand Up @@ -543,12 +543,12 @@ private void setUpCallPrimaryID(
final ParameterBody parameterBody;
if (includeIdentitiesSet) {
parameterBody = new ParameterBody(
new Parameter("include", "identities_set"),
new Parameter("include", "identity_set"),
new Parameter("token", authtoken));
} else {
parameterBody = new ParameterBody(
new Parameter("token", authtoken),
new Parameter(not("include"), not("identities_set")));
new Parameter(not("include"), not("identity_set")));
}
mockClientAndServer.when(
new HttpRequest()
Expand Down Expand Up @@ -691,7 +691,7 @@ public void getIdentityWithSecondariesAndLoginURLAndEnvironment() throws Excepti
.put("username", "aUsername")
.put("name", "fullname")
.put("email", "anEmail")
.put("identities_set",
.put("identity_set",
Arrays.asList("id1 ", "anID", "\nid2"))
.build()));

Expand Down Expand Up @@ -805,7 +805,7 @@ private void getIdentityWithoutSecondariesAndLinkURL(final String env, final Str
"username", "aUsername2",
"name", null,
"email", null,
"identities_set", Arrays.asList("anID2 \n"))));
"identity_set", Arrays.asList("anID2 \n"))));
final IdentityProviderResponse ipr = idp.getIdentities(
authCode, "pkcepkcepkcepkcepkcepkce", true, env);
assertThat("incorrect ident set", ipr, is(IdentityProviderResponse.from(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
public class ServiceCommonTest {

public static final String SERVICE_NAME = "Authentication Service";
public static final String SERVER_VER = "0.8.0";
public static final String SERVER_VER = "0.8.1";
public static final String GIT_ERR =
"Missing git commit file gitcommit, should be in us.kbase.auth2";

Expand Down
9 changes: 6 additions & 3 deletions src/test/java/us/kbase/test/auth2/service/ui/TokensTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ public void createTokenMaximalInput() throws Exception {
TokenType.LOGIN, UUID.randomUUID(),
new UserName("whoo"))
.withLifeTime(Instant.ofEpochMilli(10000), 1000000000000000L)
.withMFA(MFAStatus.USED)
.build(),
token.getHashedToken().getTokenHash());

Expand Down Expand Up @@ -464,11 +465,13 @@ public void createTokenMaximalInput() throws Exception {

UUID.fromString(id); // ensures the id is a valid uuid
TestCommon.assertCloseToNow(created);
assertThat("incorrect expires", expires, is(created + 100_000_000L * 24 * 3600 * 1000L));
assertThat(
"incorrect expires", expires, is(created + 100_000_000L * 24 * 3600 * 1000L)
);

ServiceTestUtils.checkStoredToken(manager, newtoken, id, created,
ImmutableMap.of("foo", "bar", "baz", "bat"),
new UserName("whoo"), TokenType.SERV, MFAStatus.UNKNOWN, "foo",
new UserName("whoo"), TokenType.SERV, MFAStatus.USED, "foo",
100_000_000L * 24 * 3600 * 1000L);


Expand All @@ -487,7 +490,7 @@ public void createTokenMaximalInput() throws Exception {

ServiceTestUtils.checkReturnedToken(manager, json,
ImmutableMap.of("foo", "bar", "baz", "bat"),
new UserName("whoo"), TokenType.SERV, MFAStatus.UNKNOWN, "foo",
new UserName("whoo"), TokenType.SERV, MFAStatus.USED, "foo",
100_000_000L * 24 * 3600 * 1000L, true);
}
}
Expand Down
Loading