mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-15 09:46:16 +01:00
redesign bearer tokens
This commit is contained in:
@@ -33,6 +33,8 @@ package sonia.scm.security;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import org.apache.shiro.authc.AuthenticationToken;
|
import org.apache.shiro.authc.AuthenticationToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,69 +43,48 @@ import org.apache.shiro.authc.AuthenticationToken;
|
|||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public class BearerAuthenticationToken implements AuthenticationToken
|
public final class BearerToken implements AuthenticationToken {
|
||||||
{
|
|
||||||
|
|
||||||
/** Field description */
|
private final String raw;
|
||||||
private static final long serialVersionUID = -5005335710978534182L;
|
|
||||||
|
|
||||||
//~--- constructors ---------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new BearerAuthenticationToken
|
* Constructs a new instance.
|
||||||
*
|
*
|
||||||
*
|
* @param raw raw bearer token
|
||||||
* @param token bearer token
|
|
||||||
*/
|
*/
|
||||||
public BearerAuthenticationToken(String token)
|
private BearerToken(String raw) {
|
||||||
{
|
this.raw = raw;
|
||||||
this.token = token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the token.
|
* Returns the wrapped raw format of the token.
|
||||||
*
|
*
|
||||||
*
|
* @return raw format
|
||||||
* @return token
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getCredentials()
|
public String getCredentials() {
|
||||||
{
|
return raw;
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the username or null.
|
* Returns always {@code null}.
|
||||||
*
|
*
|
||||||
*
|
* @return {@code null}
|
||||||
* @return username or null
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getPrincipal()
|
public Object getPrincipal() {
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- set methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the username.
|
* Creates a new {@link BearerToken} from raw string representation.
|
||||||
*
|
*
|
||||||
*
|
* @param raw string representation
|
||||||
* @param username username
|
*
|
||||||
|
* @return new bearer token
|
||||||
*/
|
*/
|
||||||
public void setUsername(String username)
|
public static BearerToken valueOf(String raw){
|
||||||
{
|
Preconditions.checkArgument(!Strings.isNullOrEmpty(raw), "raw token is required");
|
||||||
this.username = username;
|
return new BearerToken(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
|
||||||
|
|
||||||
/** bearer token */
|
|
||||||
private final String token;
|
|
||||||
|
|
||||||
/** username */
|
|
||||||
private String username;
|
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
import sonia.scm.group.GroupDAO;
|
import sonia.scm.group.GroupDAO;
|
||||||
import sonia.scm.security.BearerAuthenticationToken;
|
import sonia.scm.security.BearerToken;
|
||||||
import sonia.scm.user.User;
|
import sonia.scm.user.User;
|
||||||
import sonia.scm.user.UserDAO;
|
import sonia.scm.user.UserDAO;
|
||||||
import sonia.scm.user.UserTestData;
|
import sonia.scm.user.UserTestData;
|
||||||
@@ -140,7 +140,7 @@ public class LegacyRealmTest
|
|||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testDoGetAuthenticationInfoWrongToken()
|
public void testDoGetAuthenticationInfoWrongToken()
|
||||||
{
|
{
|
||||||
realm.doGetAuthenticationInfo(new BearerAuthenticationToken("test"));
|
realm.doGetAuthenticationInfo(BearerToken.valueOf("test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Realm for authentication with {@link BearerAuthenticationToken}.
|
* Realm for authentication with {@link BearerToken}.
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
@@ -100,7 +100,7 @@ public class BearerRealm extends AuthenticatingRealm
|
|||||||
this.validators = validators;
|
this.validators = validators;
|
||||||
|
|
||||||
setCredentialsMatcher(new AllowAllCredentialsMatcher());
|
setCredentialsMatcher(new AllowAllCredentialsMatcher());
|
||||||
setAuthenticationTokenClass(BearerAuthenticationToken.class);
|
setAuthenticationTokenClass(BearerToken.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
@@ -117,10 +117,10 @@ public class BearerRealm extends AuthenticatingRealm
|
|||||||
@Override
|
@Override
|
||||||
protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token)
|
protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token)
|
||||||
{
|
{
|
||||||
checkArgument(token instanceof BearerAuthenticationToken, "%s is required",
|
checkArgument(token instanceof BearerToken, "%s is required",
|
||||||
BearerAuthenticationToken.class);
|
BearerToken.class);
|
||||||
|
|
||||||
BearerAuthenticationToken bt = (BearerAuthenticationToken) token;
|
BearerToken bt = (BearerToken) token;
|
||||||
Claims c = checkToken(bt);
|
Claims c = checkToken(bt);
|
||||||
|
|
||||||
return helper.getAuthenticationInfo(c.getSubject(), bt.getCredentials(), Scopes.fromClaims(c));
|
return helper.getAuthenticationInfo(c.getSubject(), bt.getCredentials(), Scopes.fromClaims(c));
|
||||||
@@ -134,7 +134,7 @@ public class BearerRealm extends AuthenticatingRealm
|
|||||||
*
|
*
|
||||||
* @return claim
|
* @return claim
|
||||||
*/
|
*/
|
||||||
private Claims checkToken(BearerAuthenticationToken token)
|
private Claims checkToken(BearerToken token)
|
||||||
{
|
{
|
||||||
Claims claims;
|
Claims claims;
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ package sonia.scm.web;
|
|||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
import sonia.scm.plugin.Extension;
|
import sonia.scm.plugin.Extension;
|
||||||
import sonia.scm.security.BearerAuthenticationToken;
|
import sonia.scm.security.BearerToken;
|
||||||
import sonia.scm.util.HttpUtil;
|
import sonia.scm.util.HttpUtil;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
@@ -42,7 +42,7 @@ import sonia.scm.util.HttpUtil;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link BearerAuthenticationToken} from an authorization header with
|
* Creates a {@link BearerToken} from an authorization header with
|
||||||
* bearer authorization.
|
* bearer authorization.
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
@@ -53,24 +53,24 @@ public class BearerWebTokenGenerator extends SchemeBasedWebTokenGenerator
|
|||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link BearerAuthenticationToken} from an authorization header
|
* Creates a {@link BearerToken} from an authorization header
|
||||||
* with bearer authorization.
|
* with bearer authorization.
|
||||||
*
|
*
|
||||||
* @param request http servlet request
|
* @param request http servlet request
|
||||||
* @param scheme authorization scheme
|
* @param scheme authorization scheme
|
||||||
* @param authorization authorization payload
|
* @param authorization authorization payload
|
||||||
*
|
*
|
||||||
* @return {@link BearerAuthenticationToken} or {@code null}
|
* @return {@link BearerToken} or {@code null}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected BearerAuthenticationToken createToken(HttpServletRequest request,
|
protected BearerToken createToken(HttpServletRequest request,
|
||||||
String scheme, String authorization)
|
String scheme, String authorization)
|
||||||
{
|
{
|
||||||
BearerAuthenticationToken token = null;
|
BearerToken token = null;
|
||||||
|
|
||||||
if (HttpUtil.AUTHORIZATION_SCHEME_BEARER.equalsIgnoreCase(scheme))
|
if (HttpUtil.AUTHORIZATION_SCHEME_BEARER.equalsIgnoreCase(scheme))
|
||||||
{
|
{
|
||||||
token = new BearerAuthenticationToken(authorization);
|
token = BearerToken.valueOf(authorization);
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ package sonia.scm.web;
|
|||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
import sonia.scm.plugin.Extension;
|
import sonia.scm.plugin.Extension;
|
||||||
import sonia.scm.security.BearerAuthenticationToken;
|
import sonia.scm.security.BearerToken;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import sonia.scm.util.HttpUtil;
|
import sonia.scm.util.HttpUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an {@link BearerAuthenticationToken} from the {@link #COOKIE_NAME}
|
* Creates an {@link BearerToken} from the {@link #COOKIE_NAME}
|
||||||
* cookie.
|
* cookie.
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
@@ -54,17 +54,17 @@ public class CookieBearerWebTokenGenerator implements WebTokenGenerator
|
|||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an {@link BearerAuthenticationToken} from the {@link #COOKIE_NAME}
|
* Creates an {@link BearerToken} from the {@link #COOKIE_NAME}
|
||||||
* cookie.
|
* cookie.
|
||||||
*
|
*
|
||||||
* @param request http servlet request
|
* @param request http servlet request
|
||||||
*
|
*
|
||||||
* @return {@link BearerAuthenticationToken} or {@code null}
|
* @return {@link BearerToken} or {@code null}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BearerAuthenticationToken createToken(HttpServletRequest request)
|
public BearerToken createToken(HttpServletRequest request)
|
||||||
{
|
{
|
||||||
BearerAuthenticationToken token = null;
|
BearerToken token = null;
|
||||||
Cookie[] cookies = request.getCookies();
|
Cookie[] cookies = request.getCookies();
|
||||||
|
|
||||||
if (cookies != null)
|
if (cookies != null)
|
||||||
@@ -73,7 +73,7 @@ public class CookieBearerWebTokenGenerator implements WebTokenGenerator
|
|||||||
{
|
{
|
||||||
if (HttpUtil.COOKIE_BEARER_AUTHENTICATION.equals(cookie.getName()))
|
if (HttpUtil.COOKIE_BEARER_AUTHENTICATION.equals(cookie.getName()))
|
||||||
{
|
{
|
||||||
token = new BearerAuthenticationToken(cookie.getValue());
|
token = BearerToken.valueOf(cookie.getValue());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class BearerRealmTest
|
|||||||
|
|
||||||
String compact = createCompactToken(marvin.getName(), key);
|
String compact = createCompactToken(marvin.getName(), key);
|
||||||
|
|
||||||
BearerAuthenticationToken token = new BearerAuthenticationToken(compact);
|
BearerToken token = BearerToken.valueOf(compact);
|
||||||
AuthenticationInfo info = realm.doGetAuthenticationInfo(token);
|
AuthenticationInfo info = realm.doGetAuthenticationInfo(token);
|
||||||
|
|
||||||
assertNotNull(info);
|
assertNotNull(info);
|
||||||
@@ -142,7 +142,7 @@ public class BearerRealmTest
|
|||||||
Scope.valueOf("repo:*", "user:*")
|
Scope.valueOf("repo:*", "user:*")
|
||||||
);
|
);
|
||||||
|
|
||||||
AuthenticationInfo info = realm.doGetAuthenticationInfo(new BearerAuthenticationToken(compact));
|
AuthenticationInfo info = realm.doGetAuthenticationInfo(BearerToken.valueOf(compact));
|
||||||
Scope scope = info.getPrincipals().oneByType(Scope.class);
|
Scope scope = info.getPrincipals().oneByType(Scope.class);
|
||||||
assertThat(scope, Matchers.containsInAnyOrder("repo:*", "user:*"));
|
assertThat(scope, Matchers.containsInAnyOrder("repo:*", "user:*"));
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ public class BearerRealmTest
|
|||||||
expectedException.expectMessage(Matchers.containsString("claims"));
|
expectedException.expectMessage(Matchers.containsString("claims"));
|
||||||
|
|
||||||
// kick authentication
|
// kick authentication
|
||||||
realm.doGetAuthenticationInfo(new BearerAuthenticationToken(compact));
|
realm.doGetAuthenticationInfo(BearerToken.valueOf(compact));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,7 +191,7 @@ public class BearerRealmTest
|
|||||||
Date exp = new Date(System.currentTimeMillis() - 600l);
|
Date exp = new Date(System.currentTimeMillis() - 600l);
|
||||||
String compact = createCompactToken(trillian.getName(), key, exp, Scope.empty());
|
String compact = createCompactToken(trillian.getName(), key, exp, Scope.empty());
|
||||||
|
|
||||||
realm.doGetAuthenticationInfo(new BearerAuthenticationToken(compact));
|
realm.doGetAuthenticationInfo(BearerToken.valueOf(compact));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,7 +206,7 @@ public class BearerRealmTest
|
|||||||
User trillian = UserTestData.createTrillian();
|
User trillian = UserTestData.createTrillian();
|
||||||
String compact = createCompactToken(trillian.getName(), createSecureKey());
|
String compact = createCompactToken(trillian.getName(), createSecureKey());
|
||||||
|
|
||||||
realm.doGetAuthenticationInfo(new BearerAuthenticationToken(compact));
|
realm.doGetAuthenticationInfo(BearerToken.valueOf(compact));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,7 +222,7 @@ public class BearerRealmTest
|
|||||||
|
|
||||||
String compact = Jwts.builder().setSubject("test").compact();
|
String compact = Jwts.builder().setSubject("test").compact();
|
||||||
|
|
||||||
realm.doGetAuthenticationInfo(new BearerAuthenticationToken(compact));
|
realm.doGetAuthenticationInfo(BearerToken.valueOf(compact));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
import sonia.scm.security.BearerAuthenticationToken;
|
import sonia.scm.security.BearerToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -71,8 +71,8 @@ public class BearerWebTokenGeneratorTest {
|
|||||||
when(request.getHeader("Authorization")).thenReturn("Bearer asd");
|
when(request.getHeader("Authorization")).thenReturn("Bearer asd");
|
||||||
AuthenticationToken token = tokenGenerator.createToken(request);
|
AuthenticationToken token = tokenGenerator.createToken(request);
|
||||||
assertNotNull(token);
|
assertNotNull(token);
|
||||||
assertThat(token, instanceOf(BearerAuthenticationToken.class));
|
assertThat(token, instanceOf(BearerToken.class));
|
||||||
BearerAuthenticationToken bt = (BearerAuthenticationToken) token;
|
BearerToken bt = (BearerToken) token;
|
||||||
assertThat(bt.getCredentials(), equalTo("asd"));
|
assertThat(bt.getCredentials(), equalTo("asd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
import sonia.scm.security.BearerAuthenticationToken;
|
import sonia.scm.security.BearerToken;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ public class CookieBearerWebTokenGeneratorTest
|
|||||||
when(c.getValue()).thenReturn("value");
|
when(c.getValue()).thenReturn("value");
|
||||||
when(request.getCookies()).thenReturn(new Cookie[] { c });
|
when(request.getCookies()).thenReturn(new Cookie[] { c });
|
||||||
|
|
||||||
BearerAuthenticationToken token = tokenGenerator.createToken(request);
|
BearerToken token = tokenGenerator.createToken(request);
|
||||||
|
|
||||||
assertNotNull(token);
|
assertNotNull(token);
|
||||||
assertEquals("value", token.getCredentials());
|
assertEquals("value", token.getCredentials());
|
||||||
|
|||||||
Reference in New Issue
Block a user