package bo.gotthardt.oauth2.authorization; import bo.gotthardt.exception.UnauthorizedException; import bo.gotthardt.model.OAuth2AccessToken; import bo.gotthardt.model.User; import com.avaje.ebean.EbeanServer; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.net.HttpHeaders; import io.dropwizard.auth.Auth; import lombok.extern.slf4j.Slf4j; import javax.inject.Inject; import javax.ws.rs.*; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import java.time.Duration; import java.time.LocalDateTime; /** * Jersey resource that provides {@link OAuth2AccessToken}s in response to {@link OAuth2AuthorizationRequest}s. * <br/><br/> * Requires the {@link OAuth2AuthorizationRequestFactory} to be present. * * @author Bo Gotthardt */ @Slf4j @Produces(MediaType.APPLICATION_JSON) @Path("/token") public class OAuth2AccessTokenResource { private static final Duration TOKEN_LIFETIME = Duration.ofDays(365); private final EbeanServer db; @Inject public OAuth2AccessTokenResource(EbeanServer db) { this.db = db; } @POST public OAuth2AccessToken token(@Context OAuth2AuthorizationRequest authRequest) { Optional<User> user = authRequest.getValidUser(db); if (!user.isPresent()) { throw new UnauthorizedException(); } OAuth2AccessToken token = new OAuth2AccessToken(user.get(), TOKEN_LIFETIME); db.save(token); log.info("Created token for {}", user.get()); return token; } @DELETE public void delete(@Auth User user, @HeaderParam(HttpHeaders.AUTHORIZATION) String authHeader) { // Since the user was authenticated, we know that the header is present, valid and points to an access token owned by the user. String accessToken = authHeader.substring(authHeader.indexOf(" ") + 1); OAuth2AccessToken token = db.find(OAuth2AccessToken.class, accessToken); Preconditions.checkNotNull(token); Preconditions.checkState(user.getId().equals(token.getUser().getId())); token.setExpirationDate(LocalDateTime.now()); db.save(token); log.info("Expired token %s", token); } }