diff --git a/pom.xml b/pom.xml
index 721e8d3..5723a03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,6 +25,7 @@
jwt
+ tokens
diff --git a/tokens/pom.xml b/tokens/pom.xml
new file mode 100644
index 0000000..c979dde
--- /dev/null
+++ b/tokens/pom.xml
@@ -0,0 +1,133 @@
+
+
+ 4.0.0
+
+
+ io.scalecube
+ scalecube-security-parent
+ 1.0.10-SNAPSHOT
+
+
+ scalecube-security-tokens
+
+
+ 0.11.1
+
+ Dysprosium-SR7
+ 2.11.0
+ 1.7.30
+
+ 5.4.2
+ 5.0.0
+ 1.14.0
+ 3.1.0
+
+ exberry-io/${project.artifactId}
+
+
+
+
+
+
+ io.jsonwebtoken
+ jjwt-api
+ ${jjwt.version}
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ ${jjwt.version}
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ ${jjwt.version}
+
+
+
+ com.fasterxml.jackson
+ jackson-bom
+ ${jackson.version}
+ pom
+ import
+
+
+
+ io.projectreactor
+ reactor-bom
+ ${reactor.version}
+ pom
+ import
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+
+
+
+
+ io.jsonwebtoken
+ jjwt-api
+
+
+ io.jsonwebtoken
+ jjwt-impl
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+
+
+ io.projectreactor
+ reactor-core
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ ${junit-jupiter.version}
+ test
+
+
+ org.testcontainers
+ vault
+ ${testcontainers.version}
+ test
+
+
+ com.bettercloud
+ vault-java-driver
+ ${vault-java-driver.version}
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-jupiter.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit-jupiter.version}
+ test
+
+
+
+
diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtToken.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtToken.java
new file mode 100644
index 0000000..3346751
--- /dev/null
+++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtToken.java
@@ -0,0 +1,24 @@
+package io.scalecube.security.tokens.jwt;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class JwtToken {
+
+ private final Map header;
+ private final Map body;
+
+ public JwtToken(Map header, Map body) {
+ this.header = Collections.unmodifiableMap(new HashMap<>(header));
+ this.body = Collections.unmodifiableMap(new HashMap<>(body));
+ }
+
+ public Map header() {
+ return header;
+ }
+
+ public Map body() {
+ return body;
+ }
+}
diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenParser.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenParser.java
new file mode 100644
index 0000000..6b3600f
--- /dev/null
+++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenParser.java
@@ -0,0 +1,10 @@
+package io.scalecube.security.tokens.jwt;
+
+import java.security.Key;
+
+public interface JwtTokenParser {
+
+ JwtToken parseToken();
+
+ JwtToken verifyToken(Key key);
+}
diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenParserFactory.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenParserFactory.java
new file mode 100644
index 0000000..f5ef270
--- /dev/null
+++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenParserFactory.java
@@ -0,0 +1,6 @@
+package io.scalecube.security.tokens.jwt;
+
+public interface JwtTokenParserFactory {
+
+ JwtTokenParser newParser(String token);
+}
diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenResolver.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenResolver.java
new file mode 100644
index 0000000..6768c2b
--- /dev/null
+++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenResolver.java
@@ -0,0 +1,16 @@
+package io.scalecube.security.tokens.jwt;
+
+import java.util.Map;
+import reactor.core.publisher.Mono;
+
+@FunctionalInterface
+public interface JwtTokenResolver {
+
+ /**
+ * Verifies and returns token claims if everything went ok.
+ *
+ * @param token jwt token
+ * @return mono result with parsed claims (or error)
+ */
+ Mono