Skip to content

Commit 7fa3bfb

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

File tree

8 files changed

+388
-2
lines changed

8 files changed

+388
-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: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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 jakarta.inject.Singleton;
24+
import org.slf4j.Logger;
25+
import org.slf4j.LoggerFactory;
26+
27+
import java.util.Map;
28+
import java.util.Optional;
29+
30+
/**
31+
* @author Utsav Varia
32+
* @since 3.0
33+
*/
34+
@Singleton
35+
public class PasetoTokenGenerator implements TokenGenerator {
36+
37+
private static final Logger LOG = LoggerFactory.getLogger(PasetoTokenGenerator.class);
38+
39+
protected final ClaimsGenerator claimsGenerator;
40+
protected final PasetoTokenConfigurationProperties tokenConfigurationProperties;
41+
42+
public PasetoTokenGenerator(ClaimsGenerator claimsGenerator, PasetoTokenConfigurationProperties tokenConfigurationProperties) {
43+
this.claimsGenerator = claimsGenerator;
44+
this.tokenConfigurationProperties = tokenConfigurationProperties;
45+
}
46+
47+
/**
48+
* Returns Paseto Token builder based on configuration.
49+
*
50+
* @return Paseto Builder
51+
*/
52+
public PasetoBuilder<?> getPasetoBuilder() {
53+
if (tokenConfigurationProperties.getVersion() == 1) {
54+
if (tokenConfigurationProperties.getTokenType().equals("local")) {
55+
return Pasetos.V1.LOCAL.builder();
56+
} else {
57+
return Pasetos.V1.PUBLIC.builder();
58+
}
59+
} else {
60+
if (tokenConfigurationProperties.getTokenType().equals("local")) {
61+
return Pasetos.V2.LOCAL.builder();
62+
} else {
63+
return Pasetos.V2.PUBLIC.builder();
64+
}
65+
}
66+
}
67+
68+
/**
69+
* Generate a JWT from a map of claims.
70+
*
71+
* @param claims the map of claims
72+
* @return the created JWT
73+
*/
74+
protected String generate(final Map<String, Object> claims) {
75+
// claims builder
76+
final PasetoBuilder<?> builder = getPasetoBuilder();
77+
78+
// add claims
79+
for (final Map.Entry<String, Object> entry : claims.entrySet()) {
80+
builder.claim(entry.getKey(), entry.getValue());
81+
}
82+
83+
return builder.compact();
84+
}
85+
86+
@Override
87+
public Optional<String> generateToken(Authentication authentication, Integer expiration) {
88+
Map<String, Object> claims = claimsGenerator.generateClaims(authentication, expiration);
89+
return generateToken(claims);
90+
}
91+
92+
@Override
93+
public Optional<String> generateToken(Map<String, Object> claims) {
94+
return Optional.of(generate(claims));
95+
}
96+
}
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)