All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mangoo.routing.handlers.OutboundCookiesHandler Maven / Gradle / Ivy

The newest version!
package io.mangoo.routing.handlers;

import com.google.inject.Inject;
import io.mangoo.constants.ClaimKey;
import io.mangoo.constants.NotNull;
import io.mangoo.core.Application;
import io.mangoo.core.Config;
import io.mangoo.routing.Attachment;
import io.mangoo.utils.CodecUtils;
import io.mangoo.utils.DateUtils;
import io.mangoo.utils.RequestUtils;
import io.mangoo.utils.token.TokenBuilder;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.CookieImpl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.time.LocalDateTime;
import java.util.Objects;

public class OutboundCookiesHandler implements HttpHandler {
    private static final Logger LOG = LogManager.getLogger(OutboundCookiesHandler.class);
    private static final String SAME_SITE_MODE = "Strict";
    private static final int SIXTY = 60;
    private final Config config;
    private Attachment attachment;

    @Inject
    public OutboundCookiesHandler(Config config) {
        this.config = Objects.requireNonNull(config, NotNull.CONFIG);
    }
    
    @Override
    public void handleRequest(HttpServerExchange exchange) throws Exception {
        this.attachment = exchange.getAttachment(RequestUtils.getAttachmentKey());

        setSessionCookie(exchange);
        setFlashCookie(exchange);
        setAuthenticationCookie(exchange);

        nextHandler(exchange);
    }

    /**
     * Sets the session cookie to the current HttpServerExchange
     *
     * @param exchange The Undertow HttpServerExchange
     */
    protected void setSessionCookie(HttpServerExchange exchange) {
        var session = attachment.getSession();
        if (session.isInvalid()) {
            var cookie = new CookieImpl(config.getSessionCookieName())
                    .setSecure(config.isSessionCookieSecure())
                    .setValue("")
                    .setHttpOnly(true)
                    .setPath("/")
                    .setMaxAge(0)
                    .setSameSite(true)
                    .setSameSiteMode(SAME_SITE_MODE)
                    .setDiscard(true);
            
            exchange.setResponseCookie(cookie);
        } else if (session.hasChanges()) {
            try {
                String token = TokenBuilder.create()
                        .withExpires(session.getExpires())
                        .withSharedSecret(config.getSessionCookieSecret())
                        .withClaim(ClaimKey.DATA, session.getValues())
                        .build();
                
                var cookie = new CookieImpl(config.getSessionCookieName())
                        .setValue(token)
                        .setSameSite(true)
                        .setSameSiteMode(SAME_SITE_MODE)
                        .setHttpOnly(true)
                        .setPath("/")
                        .setSecure(config.isSessionCookieSecure());
                
                if (Boolean.TRUE.equals(config.isSessionCookieExpires())) {
                    cookie.setExpires(DateUtils.localDateTimeToDate(session.getExpires()));
                }

                exchange.setResponseCookie(cookie);
            } catch (Exception e) { //NOSONAR Intentionally catching exception here
                LOG.error("Failed to generate session cookie", e);
            }
        } else {
            //Ignore and send no cookie to the client
        }
    }

    /**
     * Sets the authentication cookie to the current HttpServerExchange
     *
     * @param exchange The Undertow HttpServerExchange
     */
    protected void setAuthenticationCookie(HttpServerExchange exchange) {
        var authentication = attachment.getAuthentication();
        if (authentication.isInvalid() || authentication.isLogout()) {
            var cookie = new CookieImpl(config.getAuthenticationCookieName())
                    .setSecure(config.isAuthenticationCookieSecure())
                    .setValue("")
                    .setHttpOnly(true)
                    .setPath("/")
                    .setMaxAge(0)
                    .setSameSite(true)
                    .setSameSiteMode(SAME_SITE_MODE)
                    .setDiscard(true);
            
            exchange.setResponseCookie(cookie);
        } else if (authentication.isValid()) {
            if (authentication.isRememberMe()) {
                authentication.withExpires(LocalDateTime.now().plusHours(config.getAuthenticationCookieRememberExpires()));
            } 
            
            try {
                String token = TokenBuilder.create()
                        .withExpires(authentication.getExpires())
                        .withSharedSecret(config.getAuthenticationCookieSecret())
                        .withClaim(ClaimKey.TWO_FACTOR, String.valueOf(authentication.isTwoFactor()))
                        .withSubject(authentication.getSubject())
                        .build();
                
                var cookie = new CookieImpl(config.getAuthenticationCookieName())
                        .setValue(token)
                        .setSecure(config.isAuthenticationCookieSecure())
                        .setHttpOnly(true)
                        .setSameSite(true)
                        .setPath("/")
                        .setSameSiteMode(SAME_SITE_MODE);
                            
                if (config.isAuthenticationCookieExpires()) {
                    cookie.setExpires(DateUtils.localDateTimeToDate(authentication.getExpires()));
                } 
                
                exchange.setResponseCookie(cookie);
            } catch (Exception e) { //NOSONAR Intentionally catching exception here
                LOG.error("Failed to generate authentication cookie", e);
            }
        } else {
            //Ignore and send no cookie to the client
        }
    }

    /**
     * Sets the flash cookie to current HttpServerExchange
     *
     * @param exchange The Undertow HttpServerExchange
     */
    protected void setFlashCookie(HttpServerExchange exchange) {
        var flash = attachment.getFlash();
        var form = attachment.getForm();
        
        if (flash.isDiscard() || flash.isInvalid()) {
            var cookie = new CookieImpl(config.getFlashCookieName())
                    .setHttpOnly(true)
                    .setValue("")
                    .setSecure(config.isFlashCookieSecure())
                    .setPath("/")
                    .setSameSite(true)
                    .setSameSiteMode(SAME_SITE_MODE)
                    .setDiscard(true)
                    .setMaxAge(0);

            exchange.setResponseCookie(cookie);
        } else if (flash.hasContent() || form.isKept()) {
            try {
                LocalDateTime expires = LocalDateTime.now().plusSeconds(SIXTY);
                var tokenBuilder = TokenBuilder.create()
                        .withExpires(expires)
                        .withSharedSecret(config.getFlashCookieSecret())
                        .withClaim(ClaimKey.DATA, flash.getValues());
                
                if (form.isKept()) {
                    tokenBuilder.withClaim(ClaimKey.FORM, CodecUtils.serializeToBase64(form));
                }
                
                String token = tokenBuilder.build();
                var cookie = new CookieImpl(config.getFlashCookieName())
                        .setValue(token)
                        .setSecure(config.isFlashCookieSecure())
                        .setHttpOnly(true)
                        .setSameSite(true)
                        .setPath("/")
                        .setSameSiteMode(SAME_SITE_MODE)
                        .setExpires(DateUtils.localDateTimeToDate(expires));
                
                exchange.setResponseCookie(cookie);
            } catch (Exception e) { //NOSONAR Intentionally catching exception here
                LOG.error("Failed to generate flash cookie", e); 
            }
        } else {
            //Ignore and send no cookie to the client
        }
    }

    /**
     * Handles the next request in the handler chain
     *
     * @param exchange The HttpServerExchange
     * @throws Exception Thrown when an exception occurs
     */
    protected void nextHandler(HttpServerExchange exchange) throws Exception {
        if (config.isCorsEnable()) {
            Application.getInstance(CorsHandler.class).handleRequest(exchange);            
        } else {
            Application.getInstance(ResponseHandler.class).handleRequest(exchange);  
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy