Adding skeleton for JWT authenticator
This commit is contained in:
parent
54707da343
commit
e9eaf8c273
22
pom.xml
22
pom.xml
@ -55,6 +55,7 @@
|
||||
<module>redback-keys</module>
|
||||
<module>redback-users</module>
|
||||
<module>redback-integrations</module>
|
||||
<module>redback-authentication-jwt</module>
|
||||
</modules>
|
||||
|
||||
<scm>
|
||||
@ -92,6 +93,9 @@
|
||||
<!-- The git repository, where the site content is placed -->
|
||||
<siteRepositoryUrl>scm:git:https://gitbox.apache.org/repos/asf/archiva-web-content.git</siteRepositoryUrl>
|
||||
|
||||
|
||||
<jjwt.version>0.11.2</jjwt.version>
|
||||
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
@ -780,6 +784,24 @@
|
||||
</exclusions>
|
||||
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
|
||||
<version>${jjwt.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
@ -35,5 +35,6 @@
|
||||
<module>redback-authentication-memory</module>
|
||||
<module>redback-authentication-ldap</module>
|
||||
<module>redback-authentication-users</module>
|
||||
<module>redback-authentication-jwt</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.archiva.redback</groupId>
|
||||
<artifactId>redback-authentication-providers</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>redback-authentication-jwt</artifactId>
|
||||
<properties>
|
||||
<site.staging.base>${project.parent.parent.parent.basedir}</site.staging.base>
|
||||
</properties>
|
||||
<name>Redback :: Authentication Provider :: JWT</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.archiva.redback</groupId>
|
||||
<artifactId>redback-authentication-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.archiva.redback</groupId>
|
||||
<artifactId>redback-policy</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.archiva.redback</groupId>
|
||||
<artifactId>redback-configuration</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.inject</groupId>
|
||||
<artifactId>jakarta.inject-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
@ -0,0 +1,146 @@
|
||||
package org.apache.archiva.redback.authentication.jwt;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.apache.archiva.redback.authentication.AbstractAuthenticator;
|
||||
import org.apache.archiva.redback.authentication.AuthenticationDataSource;
|
||||
import org.apache.archiva.redback.authentication.AuthenticationException;
|
||||
import org.apache.archiva.redback.authentication.AuthenticationResult;
|
||||
import org.apache.archiva.redback.authentication.Authenticator;
|
||||
import org.apache.archiva.redback.authentication.TokenBasedAuthenticationDataSource;
|
||||
import org.apache.archiva.redback.configuration.UserConfiguration;
|
||||
import org.apache.archiva.redback.configuration.UserConfigurationKeys;
|
||||
import org.apache.archiva.redback.policy.AccountLockedException;
|
||||
import org.apache.archiva.redback.policy.MustChangePasswordException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.util.Base64;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
@Service("authenticator#jwt")
|
||||
public class JwtAuthenticator extends AbstractAuthenticator implements Authenticator
|
||||
{
|
||||
public static final String ID = "JwtAuthenticator";
|
||||
public static final String PROP_ALG = "algorithm";
|
||||
public static final String PROP_PRIVATEKEY = "privateKey";
|
||||
public static final String PROP_PUBLICKEY = "publicKey";
|
||||
|
||||
|
||||
@Inject
|
||||
@Named( value = "userConfiguration#default" )
|
||||
UserConfiguration userConfiguration;
|
||||
|
||||
boolean symmetricAlg = true;
|
||||
Key key;
|
||||
KeyPair keyPair;
|
||||
String sigAlg;
|
||||
String keystoreType;
|
||||
Path keystoreFilePath;
|
||||
|
||||
|
||||
@Override
|
||||
public String getId( )
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.keystoreType = userConfiguration.getString( UserConfigurationKeys.AUTHENTICATION_JWT_KEYSTORETYPE );
|
||||
this.sigAlg = userConfiguration.getString( UserConfigurationKeys.AUTHENTICATION_JWT_SIGALG );
|
||||
if ( this.sigAlg.startsWith( "HS" ) ) {
|
||||
this.symmetricAlg = true;
|
||||
} else {
|
||||
this.symmetricAlg = false;
|
||||
}
|
||||
if (this.keystoreType.equals(UserConfigurationKeys.AUTHENTICATION_JWT_KEYSTORETYPE_MEMORY))
|
||||
{
|
||||
if ( this.symmetricAlg )
|
||||
{
|
||||
this.key = createNewSecretKey( this.sigAlg );
|
||||
} else {
|
||||
this.keyPair = createNewKeyPair( this.sigAlg );
|
||||
this.keyPair.getPublic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SecretKey createNewSecretKey( String sigAlg) {
|
||||
return Keys.secretKeyFor( SignatureAlgorithm.forName( sigAlg ));
|
||||
}
|
||||
|
||||
private KeyPair createNewKeyPair(String sigAlg) {
|
||||
return Keys.keyPairFor( SignatureAlgorithm.forName( sigAlg ));
|
||||
}
|
||||
|
||||
private SecretKey loadKeyFromFile(Path filePath) throws IOException
|
||||
{
|
||||
if ( Files.exists( filePath )) {
|
||||
Properties props = new Properties( );
|
||||
try ( InputStream in = Files.newInputStream( filePath )) {
|
||||
props.loadFromXML( in );
|
||||
}
|
||||
String algorithm = props.getProperty( PROP_ALG ).trim( );
|
||||
String secretKey = props.getProperty( PROP_PRIVATEKEY ).trim( );
|
||||
byte[] keyData = Base64.getDecoder( ).decode( secretKey.getBytes() );
|
||||
return new SecretKeySpec(keyData, algorithm);
|
||||
} else {
|
||||
throw new RuntimeException( "Could not load keyfile from path " );
|
||||
}
|
||||
}
|
||||
|
||||
private KeyPair loadPairFromFile(Path filePath) throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDataSource( AuthenticationDataSource source )
|
||||
{
|
||||
return (source instanceof TokenBasedAuthenticationDataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationResult authenticate( AuthenticationDataSource source ) throws AccountLockedException, AuthenticationException, MustChangePasswordException
|
||||
{
|
||||
if (source instanceof TokenBasedAuthenticationDataSource ) {
|
||||
TokenBasedAuthenticationDataSource tSource = (TokenBasedAuthenticationDataSource) source;
|
||||
return null;
|
||||
} else {
|
||||
throw new AuthenticationException( "The provided authentication source is not suitable for this authenticator" );
|
||||
}
|
||||
}
|
||||
}
|
@ -185,4 +185,68 @@ public interface UserConfigurationKeys
|
||||
* The locale to use for sending mails and finding mail templates
|
||||
*/
|
||||
String MAIL_DEFAULT_LOCALE = "mail.locale";
|
||||
|
||||
/**
|
||||
* Defines, where the key for JWT encryption / decryption is stored.
|
||||
* Currently only memory and plainfile are supported
|
||||
*/
|
||||
String AUTHENTICATION_JWT_KEYSTORETYPE = "authentication.jwt.keystoreType";
|
||||
String AUTHENTICATION_JWT_KEYSTORETYPE_MEMORY = "memory";
|
||||
String AUTHENTICATION_JWT_KEYSTORETYPE_PLAINFILE = "plainfile";
|
||||
String AUTHENTICATION_JWT_SIGALG = "authentication.jwt.signatureAlgorithm";
|
||||
/**
|
||||
* HMAC using SHA-256
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_HS256 = "HS256";
|
||||
/**
|
||||
* HMAC using SHA-384
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_HS384 = "HS384";
|
||||
/**
|
||||
* HMAC using SHA-512
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_HS512 = "HS512";
|
||||
/**
|
||||
* ECDSA using P-256 and SHA-256
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_ES256 = "ES256";
|
||||
/**
|
||||
* ECDSA using P-384 and SHA-384
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_ES384 = "ES384";
|
||||
/**
|
||||
* ECDSA using P-521 and SHA-512
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_ES512 = "ES512";
|
||||
/**
|
||||
* RSASSA-PKCS-v1_5 using SHA-256
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_RS256 = "RS256";
|
||||
/**
|
||||
* RSASSA-PKCS-v1_5 using SHA-384
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_RS384 = "RS384";
|
||||
/**
|
||||
* RSASSA-PKCS-v1_5 using SHA-512
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_RS512 = "RS512";
|
||||
/**
|
||||
* RSASSA-PSS using SHA-256 and MGF1 with SHA-256
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_PS256 = "PS256";
|
||||
/**
|
||||
* RSASSA-PSS using SHA-384 and MGF1 with SHA-384
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_PS384 = "PS384";
|
||||
/**
|
||||
* RSASSA-PSS using SHA-512 and MGF1 with SHA-512
|
||||
*/
|
||||
String AUTHENTICATION_JWT_SIGALG_PS512 = "PS512";
|
||||
|
||||
|
||||
/**
|
||||
* Path to the file where the JWT key is stored
|
||||
*/
|
||||
String AUTHENTICATION_JWT_KEYFILE = "authentication.jwt.keyfile";
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user