Skip to content

Commit ddb3238

Browse files
committed
ENH: Added Paseto token generator
1 parent 6902722 commit ddb3238

File tree

8 files changed

+386
-2
lines changed

8 files changed

+386
-2
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ spockVersion=2.0-groovy-3.0
77

88
gebVersion=4.1
99
seleniumVersion=3.141.59
10-
jpasetoVersion = '0.7.0'
10+
jpasetoVersion = 0.7.0
1111

1212
title=Micronaut Security
1313
projectDesc=Official Security Solution for Micronaut

security-paseto/src/main/java/io/micronaut/security/token/paseto/config/PasetoConfigurationProperties.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ public class PasetoConfigurationProperties implements PasetoConfiguration {
3535
/**
3636
* The default enable value.
3737
*/
38-
@SuppressWarnings("WeakerAccess")
3938
public static final boolean DEFAULT_ENABLED = true;
4039

4140
private boolean enabled = DEFAULT_ENABLED;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2017-2020 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 \(the "License"\);
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.micronaut.security.token.paseto.generator;
18+
19+
/**
20+
* @author Utsav Varia
21+
* @since 3.0
22+
*/
23+
public interface PasetoTokenConfiguration {
24+
25+
/**
26+
* @return Paseto Version
27+
*/
28+
default int getVersion() {
29+
return 1;
30+
}
31+
32+
default String getTokenType() {
33+
return "local";
34+
}
35+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2017-2020 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 \(the "License"\);
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.micronaut.security.token.paseto.generator;
18+
19+
import io.micronaut.context.annotation.ConfigurationProperties;
20+
import io.micronaut.security.token.paseto.config.PasetoConfigurationProperties;
21+
22+
/**
23+
* @author Utsav Varia
24+
* @since 3.0
25+
*/
26+
@ConfigurationProperties(PasetoTokenConfigurationProperties.PREFIX)
27+
public class PasetoTokenConfigurationProperties implements PasetoTokenConfiguration {
28+
29+
public static final String PREFIX = PasetoConfigurationProperties.PREFIX + "token";
30+
31+
/**
32+
* The default token type. Possible values local, public.
33+
*/
34+
public static final String DEFAULT_TOKEN_TYPE = "local";
35+
36+
/**
37+
* The default Paseto version. Possible values 1, 2.
38+
*/
39+
public static final int DEFAULT_VERSION = 1;
40+
41+
private String tokenType = DEFAULT_TOKEN_TYPE;
42+
private int version = DEFAULT_VERSION;
43+
44+
/**
45+
* @return An integer indicating version of paseto
46+
*/
47+
@Override
48+
public int getVersion() {
49+
return version;
50+
}
51+
52+
/**
53+
* Sets Paseto version. Default value ({@value #DEFAULT_VERSION}).
54+
*
55+
* @param version Paseto version
56+
*/
57+
public void setVersion(int version) {
58+
this.version = version;
59+
}
60+
61+
/**
62+
* @return return token type
63+
*/
64+
@Override
65+
public String getTokenType() {
66+
return tokenType;
67+
}
68+
69+
/**
70+
* Sets Paseto token type. Default value ({@value #DEFAULT_TOKEN_TYPE})
71+
*
72+
* @param tokenType Paseto token type
73+
*/
74+
public void setTokenType(String tokenType) {
75+
this.tokenType = tokenType;
76+
}
77+
78+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2017-2020 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 \(the "License"\);
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.security.token.paseto.generator;
17+
18+
import dev.paseto.jpaseto.PasetoBuilder;
19+
import dev.paseto.jpaseto.Pasetos;
20+
import io.micronaut.security.authentication.Authentication;
21+
import io.micronaut.security.token.generator.TokenGenerator;
22+
import io.micronaut.security.token.paseto.generator.claims.ClaimsGenerator;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
26+
import java.util.Map;
27+
import java.util.Optional;
28+
29+
/**
30+
* @author Utsav Varia
31+
* @since 3.0
32+
*/
33+
public class PasetoTokenGenerator implements TokenGenerator {
34+
35+
private static final Logger LOG = LoggerFactory.getLogger(PasetoTokenGenerator.class);
36+
37+
protected final ClaimsGenerator claimsGenerator;
38+
protected final PasetoTokenConfigurationProperties tokenConfigurationProperties;
39+
40+
public PasetoTokenGenerator(ClaimsGenerator claimsGenerator, PasetoTokenConfigurationProperties tokenConfigurationProperties) {
41+
this.claimsGenerator = claimsGenerator;
42+
this.tokenConfigurationProperties = tokenConfigurationProperties;
43+
}
44+
45+
/**
46+
* Returns Paseto Token builder based on configuration.
47+
*
48+
* @return Paseto Builder
49+
*/
50+
public PasetoBuilder<?> getPasetoBuilder() {
51+
if (tokenConfigurationProperties.getVersion() == 1) {
52+
if (tokenConfigurationProperties.getTokenType().equals("local")) {
53+
return Pasetos.V1.LOCAL.builder();
54+
} else {
55+
return Pasetos.V1.PUBLIC.builder();
56+
}
57+
} else {
58+
if (tokenConfigurationProperties.getTokenType().equals("local")) {
59+
return Pasetos.V2.LOCAL.builder();
60+
} else {
61+
return Pasetos.V2.PUBLIC.builder();
62+
}
63+
}
64+
}
65+
66+
/**
67+
* Generate a JWT from a map of claims.
68+
*
69+
* @param claims the map of claims
70+
* @return the created JWT
71+
*/
72+
protected String generate(final Map<String, Object> claims) {
73+
// claims builder
74+
final PasetoBuilder<?> builder = getPasetoBuilder();
75+
76+
// add claims
77+
for (final Map.Entry<String, Object> entry : claims.entrySet()) {
78+
builder.claim(entry.getKey(), entry.getValue());
79+
}
80+
81+
return builder.compact();
82+
}
83+
84+
@Override
85+
public Optional<String> generateToken(Authentication authentication, Integer expiration) {
86+
Map<String, Object> claims = claimsGenerator.generateClaims(authentication, expiration);
87+
return generateToken(claims);
88+
}
89+
90+
@Override
91+
public Optional<String> generateToken(Map<String, Object> claims) {
92+
return Optional.of(generate(claims));
93+
}
94+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2017-2020 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 \(the "License"\);
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.security.token.paseto.generator.claims;
17+
18+
import io.micronaut.security.authentication.Authentication;
19+
20+
import java.util.Map;
21+
22+
/**
23+
* @author Utsav Varia
24+
* @since 3.0
25+
*/
26+
public interface ClaimsGenerator {
27+
28+
/**
29+
*
30+
* @param authentication Authenticated user's representation.
31+
* @param expiration JWT token expiration time in seconds
32+
* @return The Claims
33+
*/
34+
Map<String, Object> generateClaims(Authentication authentication, Integer expiration);
35+
36+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2017-2020 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 \(the "License"\);
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.micronaut.security.token.paseto.generator.claims;
18+
19+
import io.micronaut.security.authentication.Authentication;
20+
import io.micronaut.security.token.config.TokenConfiguration;
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
24+
import java.util.Map;
25+
26+
/**
27+
* @author Utsav Varia
28+
* @since 3.0
29+
*/
30+
public class PasetoClaimsGenerator implements ClaimsGenerator {
31+
32+
private static final Logger LOG = LoggerFactory.getLogger(PasetoClaimsGenerator.class);
33+
private static final String ROLES_KEY = "rolesKey";
34+
35+
private final TokenConfiguration tokenConfiguration;
36+
37+
public PasetoClaimsGenerator(TokenConfiguration tokenConfiguration) {
38+
this.tokenConfiguration = tokenConfiguration;
39+
}
40+
41+
/**
42+
* Populates sub claim.
43+
*
44+
* @param builder The Paseto Claims Builder
45+
* @param authentication Authenticated user's representation.
46+
*/
47+
protected void populateSub(PasetoClaimsSet.Builder builder, Authentication authentication) {
48+
builder.claim("sub", authentication.getName()); // sub
49+
}
50+
51+
@Override
52+
public Map<String, Object> generateClaims(Authentication authentication, Integer expiration) {
53+
// Builder for PasetoClaims
54+
PasetoClaimsSet.Builder builder = new PasetoClaimsSet.Builder();
55+
56+
populateSub(builder, authentication);
57+
authentication.getAttributes().forEach(builder::claim);
58+
String rolesKey = tokenConfiguration.getRolesName();
59+
if (!rolesKey.equalsIgnoreCase(TokenConfiguration.DEFAULT_ROLES_NAME)) {
60+
builder.claim(ROLES_KEY, rolesKey);
61+
}
62+
builder.claim(rolesKey, authentication.getRoles());
63+
64+
PasetoClaimsSet claimsSet = builder.build();
65+
66+
if (LOG.isDebugEnabled()) {
67+
LOG.debug("Generated claim set: {}", claimsSet.getClaims().toString());
68+
}
69+
70+
return claimsSet.getClaims();
71+
}
72+
}

0 commit comments

Comments
 (0)