
keywhiz.auth.cookie.AuthenticatedEncryptedCookieFactory Maven / Gradle / Ivy
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed 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.
*/
package keywhiz.auth.cookie;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Throwables;
import java.time.Clock;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.Base64;
import javax.crypto.AEADBadTagException;
import javax.inject.Inject;
import javax.ws.rs.core.NewCookie;
import keywhiz.auth.User;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.server.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.nio.charset.StandardCharsets.UTF_8;
/** Produces tokens and cookies based on encrypted {@link UserCookieData} records. */
public class AuthenticatedEncryptedCookieFactory {
private static final Logger logger = LoggerFactory.getLogger(AuthenticatedEncryptedCookieFactory.class);
private final Clock clock;
private final ObjectMapper mapper;
private final GCMEncryptor encryptor;
private final CookieConfig config;
/**
* @param clock to use for resolving current time
* @param mapper json serializer
* @param encryptor performs authenticated-encryption using a non-colliding counter specific to a host.
* @param config parameters for cookie generation
*/
@Inject
public AuthenticatedEncryptedCookieFactory(
Clock clock,
ObjectMapper mapper,
GCMEncryptor encryptor,
@SessionCookie CookieConfig config) {
this.clock = clock;
this.mapper = mapper;
this.encryptor = encryptor;
this.config = config;
}
/**
* Produces an authenticating token.
*
* @param user identity the token will authenticate.
* @param expiration timestamp when token should expire.
* @return token which can be used to authenticate as user until expiration.
*/
public String getSession(User user, ZonedDateTime expiration) {
try {
String cookieJson = mapper.writeValueAsString(new UserCookieData(user, expiration));
byte[] cookieBody = encryptor.encrypt(cookieJson.getBytes(UTF_8));
return Base64.getEncoder().encodeToString(cookieBody);
} catch (AEADBadTagException e) {
logger.error("Could not encrypt cookie", e);
throw Throwables.propagate(e);
} catch (JsonProcessingException e) {
throw Throwables.propagate(e);
}
}
/**
* Produces a cookie string for a given value and expiration.
*
* @param value value of new cookie.
* @param expiration expiration time of cookie.
* @return serialized cookie with given value and expiration.
*/
public NewCookie cookieFor(String value, ZonedDateTime expiration) {
long maxAge = Duration.between(ZonedDateTime.now(clock), expiration).getSeconds();
HttpCookie cookie = new HttpCookie(config.getName(), value, config.getDomain(),
config.getPath(), maxAge, config.isHttpOnly(), config.isSecure());
Response response = new Response(null, null);
response.addCookie(cookie);
return NewCookie.valueOf(response.getHttpFields().getStringField(HttpHeader.SET_COOKIE));
}
/**
* Shortcut method to produce an authenticated cookie string.
*
* @param user identity the token will authenticate.
* @param expiration timestamp when cookie should expire.
* @return serialized cookie which can be used to authenticate as user until expiration.
*/
public NewCookie getSessionCookie(User user, ZonedDateTime expiration) {
return cookieFor(getSession(user, expiration), expiration);
}
/**
* Produces an expired cookie string, used to update/overwrite an existing cookie.
*
* @return serialized expired cookie with matching parameters to authenticating cookie.
*/
public NewCookie getExpiredSessionCookie() {
HttpCookie cookie = new HttpCookie(config.getName(), "expired", config.getDomain(), config.getPath(),
0, config.isHttpOnly(), config.isSecure());
Response response = new Response(null, null);
response.addCookie(cookie);
return NewCookie.valueOf(response.getHttpFields().getStringField(HttpHeader.SET_COOKIE));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy