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

io.restassured.authentication.FormAuthConfig Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Copyright 2019 the original author or authors.
 *
 * 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 io.restassured.authentication;

import io.restassured.config.LogConfig;
import io.restassured.filter.log.LogDetail;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static io.restassured.internal.common.assertion.AssertParameter.notNull;
import static java.lang.String.format;

/**
 * Configuration of form authentication to correctly identify which form that contains the username and password
 * and the action of the form.
 */
public class FormAuthConfig {
    private final String formAction;
    private final String userInputTagName;
    private final String passwordInputTagName;
    private final LogConfig logConfig;
    private final LogDetail logDetail;
    private final List additionalInputFieldNames;
    private final String csrfFieldName;
    private final boolean autoDetectCsrfFieldName;
    private final boolean sendCsrfTokenAsFormParam;

    /**
     * Create a form auth config with a pre-defined form action, username input tag, password input tag.
     * E.g. let's say that the login form on your login page looks like this:
     * 
     *  <form action="/j_spring_security_check">
     *     <label for="j_username">Username</label>
     *     <input type="text" name="j_username" id="j_username"/>
     *     <br/>
     *     <label for="j_password">Password</label>
     *     <input type="password" name="j_password" id="j_password"/>
     *     <br/>
     *     <input type='checkbox' name='_spring_security_remember_me'/> Remember me on this computer.
     *     <br/>
     *     <input type="submit" value="Login"/>
     * </form>
     * 
*

* This means that formAction should be set to /j_spring_security_check, userNameInputTagName * should be set to j_username and passwordInputTagName should be set to j_password. * * @param formAction The action of the form * @param userNameInputTagName The name of the username input tag in the login form * @param passwordInputTagName The name of the password input tag in the login form */ public FormAuthConfig(String formAction, String userNameInputTagName, String passwordInputTagName) { this(formAction, userNameInputTagName, passwordInputTagName, null, null, null, false, true, Collections.emptyList()); } /** * Creates a new empty {@link FormAuthConfig}. */ public FormAuthConfig() { this(null, null, null); } private FormAuthConfig(String formAction, String userNameInputTagName, String passwordInputTagName, LogDetail logDetail, LogConfig logConfig, String csrfFieldName, boolean autoDetectCsrfFieldName, boolean sendCsrfTokenAsFormParam, List additionalInputFieldNames) { this.formAction = formAction; this.userInputTagName = userNameInputTagName; this.passwordInputTagName = passwordInputTagName; this.logDetail = logDetail; this.logConfig = logConfig; this.csrfFieldName = csrfFieldName; this.autoDetectCsrfFieldName = autoDetectCsrfFieldName; this.sendCsrfTokenAsFormParam = sendCsrfTokenAsFormParam; this.additionalInputFieldNames = Collections.unmodifiableList(additionalInputFieldNames); } /** * @return A predefined form authentication config for default Spring Security configuration (tested in version 3.0.5) (no CSRF detection). */ public static FormAuthConfig springSecurity() { return new FormAuthConfig("/j_spring_security_check", "j_username", "j_password"); } /** * Enable Cross-site request forgery (csrf) support when using form authentication by including the csrf value of the input field with the specified name. * For example if the login page looks like this: *

     * <html>
     * <head>
     *     <title>Login</title>
     * </head>
     * <body>
     * <form action="j_spring_security_check_with_csrf" method="POST">
     *     <table>
     *         <tr>
     *             <td>User:&nbsp;</td>
     *             <td><input type="text" name="j_username"></td>
     *         </tr>
     *         <tr>
     *             <td>Password:</td>
     *             <td><input type="password" name="j_password"></td>
     *         </tr>
     *         <tr>
     *             <td colspan="2"><input name="submit" type="submit"/></td>
     *         </tr>
     *     </table>
     *     <input type="hidden" name="_csrf" value="8adf2ea1-b246-40aa-8e13-a85fb7914341"/>
     * </form>
     * </body>
     * </html>
     * 
* The csrf field name is called _csrf. *

* Important: When enabling csrf support then REST Assured must always make an additional request to the server in order to * be able to include in the csrf value which will slow down the tests. * * @param fieldName The name of the input field * @return A new FormAuthConfig instance. * @see #withAutoDetectionOfCsrf() */ public FormAuthConfig withCsrfFieldName(String fieldName) { notNull(fieldName, "CSRF field name"); if (autoDetectCsrfFieldName) { throw new IllegalStateException("Cannot defined a CSRF field name since the CSRF field name has been marked as auto-detected."); } return new FormAuthConfig(formAction, userInputTagName, passwordInputTagName, logDetail, logConfig, fieldName, false, sendCsrfTokenAsFormParam, additionalInputFieldNames); } /** * Include additional field when using form authentication by including input field value with the specified name. * For example if the login page looks like this: *

     * <html>
     * <head>
     *     <title>Login</title>
     * </head>
     * <body>
     * <form action="j_spring_security_check_with_csrf" method="POST">
     *     <table>
     *         <tr>
     *             <td>User:&nbsp;</td>
     *             <td><input type="text" name="j_username"></td>
     *         </tr>
     *         <tr>
     *             <td>Password:</td>
     *             <td><input type="password" name="j_password"></td>
     *         </tr>
     *         <tr>
     *             <td colspan="2"><input name="submit" type="submit"/></td>
     *         </tr>
     *     </table>
     *     <input type="hidden" name="something" value="8adf2ea1-b246-40aa-8e13-a85fb7914341"/>
     * </form>
     * </body>
     * </html>
     * 
* and you'd like to include the field named something as an additional form parameter in the request you can do like this: * *
     * given().auth().form(..., new FormAuthConfig(..).withAdditionalField("something"). ..
     * 
* and then REST Assured will send the form parameter something=8adf2ea1-b246-40aa-8e13-a85fb7914341 * *

* Important: When including an additional field without specifying a value then REST Assured must always make an additional request to the server in order to * be able to figure out the field value. This will slow down the tests. * * @param fieldName The first field name to include * @return A new FormAuthConfig instance. */ public FormAuthConfig withAdditionalField(String fieldName) { notNull(fieldName, "Additional field name"); List list = new ArrayList(additionalInputFieldNames); list.add(fieldName); return new FormAuthConfig(formAction, userInputTagName, passwordInputTagName, logDetail, logConfig, csrfFieldName, autoDetectCsrfFieldName, sendCsrfTokenAsFormParam, list); } /** * Include multiple additional fields when using form authentication by including input field values with the specified name. * This is the same as {@link #withAdditionalField(String)} but for multiple fields. * *

* Important: When including an additional field without specifying a value then REST Assured must always make an additional request to the server in order to * be able to figure out the field value. This will slow down the tests. * * @param firstFieldName The first additional input field to include * @param secondFieldName The second additional input field to include * @param additionalFieldNames Additional field name to include (optional) * @return A new FormAuthConfig instance. */ public FormAuthConfig withAdditionalFields(String firstFieldName, String secondFieldName, String... additionalFieldNames) { notNull(firstFieldName, "First additional field name"); notNull(secondFieldName, "Second additional field name"); List list = new ArrayList(additionalInputFieldNames); list.add(firstFieldName); list.add(secondFieldName); if (additionalFieldNames != null && additionalFieldNames.length > 0) { list.addAll(Arrays.asList(additionalFieldNames)); } return new FormAuthConfig(formAction, userInputTagName, passwordInputTagName, logDetail, logConfig, csrfFieldName, autoDetectCsrfFieldName, sendCsrfTokenAsFormParam, list); } /** * @return Configure form authentication to send the csrf token in a header. */ public FormAuthConfig sendCsrfTokenAsHeader() { return new FormAuthConfig(formAction, userInputTagName, passwordInputTagName, logDetail, logConfig, csrfFieldName, autoDetectCsrfFieldName, false, additionalInputFieldNames); } /** * @return Configure form authentication to send the csrf token as a form parameter (default setting). */ public FormAuthConfig sendCsrfTokenAsFormParam() { return new FormAuthConfig(formAction, userInputTagName, passwordInputTagName, logDetail, logConfig, csrfFieldName, autoDetectCsrfFieldName, true, additionalInputFieldNames); } /** * Enable Cross-site request forgery (csrf) support when using form authentication by automatically trying to find the name and value of the csrf input field. * For example if the login page looks like this: *

     * <html>
     * <head>
     *     <title>Login</title>
     * </head>
     * <body>
     * <form action="j_spring_security_check_with_csrf" method="POST">
     *     <table>
     *         <tr>
     *             <td>User:&nbsp;</td>
     *             <td><input type="text" name="j_username"></td>
     *         </tr>
     *         <tr>
     *             <td>Password:</td>
     *             <td><input type="password" name="j_password"></td>
     *         </tr>
     *         <tr>
     *             <td colspan="2"><input name="submit" type="submit"/></td>
     *         </tr>
     *     </table>
     *     <input type="hidden" name="_csrf" value="8adf2ea1-b246-40aa-8e13-a85fb7914341"/>
     * </form>
     * </body>
     * </html>
     * 
* The csrf field name is called _csrf and REST Assured will autodetect its name since the field name is the only hidden field on this page. * If auto-detection fails you can consider using {@link #withCsrfFieldName(String)}. *

* Important: When enabling csrf support then REST Assured must always make an additional request to the server in order to * be able to include in the csrf value which will slow down the tests. * * @return A new FormAuthConfig instance. * @see #withCsrfFieldName(String) */ public FormAuthConfig withAutoDetectionOfCsrf() { if (hasCsrfFieldName()) { throw new IllegalStateException(format("Cannot use auto-detection of CSRF field name since a CSRF field name was already defined as '%s'", csrfFieldName)); } return new FormAuthConfig(formAction, userInputTagName, passwordInputTagName, logDetail, logConfig, csrfFieldName, true, sendCsrfTokenAsFormParam, additionalInputFieldNames); } /** * Enables logging with log level {@link LogDetail#ALL} of the request made to authenticate using * form authentication. Both the request and the response is logged. * * @return A new FormAuthConfig instance. */ public FormAuthConfig withLoggingEnabled() { return withLoggingEnabled(LogDetail.ALL); } /** * Enables logging with the supplied logDetail of the request made to authenticate using form authentication. * Both the request and the response is logged. * * @return A new FormAuthConfig instance. */ public FormAuthConfig withLoggingEnabled(LogDetail logDetail) { return withLoggingEnabled(logDetail, new LogConfig()); } /** * Enables logging with log level {@link LogDetail#ALL} of the request made to authenticate using * form authentication using the specified {@link LogConfig}. Both the request and the response is logged. * * @return A new FormAuthConfig instance. */ public FormAuthConfig withLoggingEnabled(LogConfig logConfig) { return withLoggingEnabled(LogDetail.ALL, logConfig); } /** * Enables logging with the supplied log detail of the request made to authenticate using form authentication using the * specified {@link LogConfig}. Both the request and the response is logged. * * @return A new FormAuthConfig instance. */ public FormAuthConfig withLoggingEnabled(LogDetail logDetail, LogConfig logConfig) { notNull(logDetail, LogDetail.class); notNull(logConfig, LogConfig.class); return new FormAuthConfig(formAction, userInputTagName, passwordInputTagName, logDetail, logConfig, csrfFieldName, autoDetectCsrfFieldName, sendCsrfTokenAsFormParam, additionalInputFieldNames); } /** * Creates a new empty {@link FormAuthConfig}. * * @return A new FormAuthConfig instance. */ public static FormAuthConfig formAuthConfig() { return new FormAuthConfig(null, null, null); } /** * Syntactic sugar * * @return The same FormAuthConfig instance */ public FormAuthConfig and() { return this; } public String getFormAction() { return formAction; } public String getUserInputTagName() { return userInputTagName; } /** * @return The password input tag name or null if undefined */ public String getPasswordInputTagName() { return passwordInputTagName; } /** * @return The logging configuration */ public LogConfig getLogConfig() { return logConfig; } /** * @return true if logging is enabled or false otherwise. */ public boolean isLoggingEnabled() { return logConfig != null && logDetail != null; } /** * @return The specified log detail or null if undefined */ public LogDetail getLogDetail() { return logDetail; } /** * @return The specified csrf field name or null if undefined */ public String getCsrfFieldName() { return csrfFieldName; } /** * @return The additional input field names */ public List getAdditionalInputFieldNames() { return additionalInputFieldNames; } /** * @return true if csrf field name is defined or false otherwise. */ public boolean hasCsrfFieldName() { return StringUtils.isNotBlank(csrfFieldName); } /** * @return true if additional input field name have been specified or false otherwise. */ public boolean hasAdditionalInputFieldNames() { return !additionalInputFieldNames.isEmpty(); } /** * @return true if auto detection of csrf field name is enabled, false otherwise. */ public boolean isAutoDetectCsrfFieldName() { return autoDetectCsrfFieldName; } /** * @return true if the user input tag name is defined or false otherwise. */ public boolean hasUserInputTagName() { return StringUtils.isNotBlank(userInputTagName); } /** * @return true if the password input tag name is defined or false otherwise. */ public boolean hasPasswordInputTagName() { return StringUtils.isNotBlank(passwordInputTagName); } /** * @return true if the form action is defined or false otherwise. */ public boolean hasFormAction() { return StringUtils.isNotBlank(formAction); } /** * @return true if the {@link FormAuthConfig} instance contains settings that require REST Assured to make a request to the server before applying form authentication, false otherwise. */ public boolean requiresParsingOfLoginPage() { return !hasFormAction() || !hasUserInputTagName() || !hasPasswordInputTagName() || isAutoDetectCsrfFieldName() || hasCsrfFieldName() ||hasAdditionalInputFieldNames(); } /** * @return true if the csrf token should be sent as a form param or false if it's sent as a header. */ public boolean shouldSendCsrfTokenAsFormParam() { return sendCsrfTokenAsFormParam; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy