|
| 1 | +# Authentication with WFC |
| 2 | + |
| 3 | +The API/SUT might require authenticated requests. |
| 4 | +And there are several different mechanism to do authentication. |
| 5 | + |
| 6 | +This documentation explains, with some examples, how WFC can be used to create auth configuration files using the JSON Schema defined in [auth.yaml](src/main/resources/wfc/schemas/auth.yaml). |
| 7 | + |
| 8 | +The idea is to define in configuration files (e.g., in YAML and TOML formats) how authentication can be done, by defining info for some users. |
| 9 | +This information needs to be actually existing and valid, as the APIs will need to validate it. |
| 10 | + |
| 11 | +As this info is specific to the testing environment in which the fuzzing is done, it is not something that should be really specified in the API schemas (e.g., OpenAPI for REST). |
| 12 | +Therefore, separated configurations are a necessity. |
| 13 | + |
| 14 | +These configuration files just specify _how_ authentication can be done with concrete values (e.g., user ids and passwords). |
| 15 | +Still, it is up to the fuzzers to read such information, and then make the correct authentication calls. |
| 16 | + |
| 17 | +> __NOTE:__ If the type of authentication you need is not currently supported, please open a new feature request on [our issue page](https://github.com/WebFuzzing/Commons/issues). |
| 18 | +
|
| 19 | + |
| 20 | +## Static Tokens |
| 21 | + |
| 22 | +``` |
| 23 | +auth: |
| 24 | + - name: FOO |
| 25 | + fixedHeaders: |
| 26 | + - name: Authorization |
| 27 | + value: " some static token for FOO" |
| 28 | + - name: BAR |
| 29 | + fixedHeaders: |
| 30 | + - name: Authorization |
| 31 | + value: " some static token for BAR" |
| 32 | +``` |
| 33 | + |
| 34 | +An array called `auth` is instantiated, having each entry representing the authentication info for different users. |
| 35 | +In this example, two users are defined: _FOO_ and _BAR_. |
| 36 | +The names here are just for documentation (e.g., fuzzers could use such names as comments when generating test cases using such info). |
| 37 | + |
| 38 | +When they need to authenticate, these users require some fixed values in some specified HTTP header, sent on each HTTP call. |
| 39 | +This is for example what needed in HTTP Basic (RFC-7617). |
| 40 | +The "token" here is static, e.g., not changing. |
| 41 | +This could be for example including userid and password of the user, possibly encoded in different formats (e.g., Base64). |
| 42 | +Such credentials (i.e., userid/password) would not change per user, and so can be specified only once. |
| 43 | + |
| 44 | +Everytime a fuzzer want to make an authenticated call with user _BAR_, based on that information it should send the HTTP requests with `Authorization: some static token for BAR` header. |
| 45 | + |
| 46 | +Static tokens are not really recommended, and should be avoided. |
| 47 | +Still, WFC enables to support their definition, if needed. |
| 48 | + |
| 49 | +## Dynamic Tokens |
| 50 | + |
| 51 | +A common practice is to send a login request to a login endpoint (on same the API, or a third-party one), and extract a _dynamic_ token from the response. |
| 52 | +The token can be used in following HTTP requests. |
| 53 | +The token will be specific for the user, and have a limited lifespan in which it is valid for authentication. |
| 54 | + |
| 55 | +Let's consider this following example of configuration: |
| 56 | + |
| 57 | +``` |
| 58 | +auth: |
| 59 | + - name: foo |
| 60 | + loginEndpointAuth: |
| 61 | + payloadRaw: "{\"username\": \"foo\", \"password\": \"123\"}" |
| 62 | + - name: bar |
| 63 | + loginEndpointAuth: |
| 64 | + payloadUserPwd: |
| 65 | + username: bar |
| 66 | + password: "456" |
| 67 | + usernameField: username |
| 68 | + passwordField: password |
| 69 | +
|
| 70 | +authTemplate: |
| 71 | + loginEndpointAuth: |
| 72 | + endpoint: /login |
| 73 | + verb: POST |
| 74 | + contentType: application/json |
| 75 | + expectCookies: true |
| 76 | +``` |
| 77 | + |
| 78 | +Here, 2 example users are specified under `auth`: `foo` and `bar`, with their passwords. |
| 79 | + |
| 80 | +The payload sent to the login endpoint could be either specified as it is (i.e., with `payloadRaw`), or with username/password separately (from which the right payload is automatically derived and formatted based on the `contentType`, e.g., `application/json` or `application/x-www-form-urlencoded`). |
| 81 | + |
| 82 | +There are several pieces of information that would be the same for both users: |
| 83 | +* `endpoint`: the path for the endpoint with the login (can use `externalEndpointURL` if it is on a different server). |
| 84 | +* `verb`: the HTTP verb used to make the request (typically it is a `POST`). |
| 85 | +* `contentType`: specify how the payload will be sent (e.g., JSON in this case). |
| 86 | +* `expectCookies`: tell the fuzzer that from the login endpoint we expect to get a cookie for the authentication. |
| 87 | + |
| 88 | +To avoid duplication, shared info can be defined in the `authTemplate` object. |
| 89 | + |
| 90 | +Note that, at times, username/password information might be passed via a header (e.g., with `Basic`), instead of with a body payload. |
| 91 | +This is supported with the array `headers`, in which each header can be specified with a `name` and `value`. |
| 92 | +For example: |
| 93 | + |
| 94 | +``` |
| 95 | +auth: |
| 96 | + - name: test |
| 97 | + loginEndpointAuth: |
| 98 | + endpoint: /api/login |
| 99 | + verb: POST |
| 100 | + headers: |
| 101 | + - name: Authorization |
| 102 | + value: "Basic dGVzdDp0ZXN0Cg==" |
| 103 | +``` |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | +If instead of cookies we have a token to be extracted from the JSON response of the login endpoint, we can use something like: |
| 108 | + |
| 109 | +``` |
| 110 | +auth: |
| 111 | + loginEndpointAuth: |
| 112 | + # ... other data here |
| 113 | + token: |
| 114 | + headerPrefix="Bearer " |
| 115 | + extractFromField = "/token/authToken" |
| 116 | + httpHeaderName="Authorization" |
| 117 | +``` |
| 118 | + |
| 119 | +What will happen here is that a fuzzer will make a POST to `/login` and then extract the field `token.authToken` from the JSON response (the entry `extractFromField` is treated as a JSON Pointer (RFC 6901)). |
| 120 | +Assume for example we have `token.authToken = 123456`. |
| 121 | +In the following auth requests, then the fuzzer will make requests with HTTP header: `Authorization:Bearer 123456`. |
| 122 | + |
| 123 | + |
| 124 | +## Fuzzer Configurations |
| 125 | + |
| 126 | +Having right authentication credentials is essential when testing real-world APIs. |
| 127 | +As such, preparing an authentication configuration file would hence become a common practice. |
| 128 | +Still, the fuzzer itself might have different configuration settings not related to authentication (e.g., related to where to output the generated tests, and for how long to run the fuzzer). |
| 129 | +Such info could be passed on the command-line as program inputs, or specified in a configuration file. |
| 130 | +In this latter case, having two different configuration files (one for authentication and one for internal settings) might be cumbersome. |
| 131 | + |
| 132 | +To avoid such issue, WFC Authentication supports the object `configs`. |
| 133 | +This is an object of string fields. |
| 134 | +It can be treated as a map/dictionary of `key:value` pairs. |
| 135 | +Each key is a fuzzer configuration property, with given chosen value. |
| 136 | +As each configuration property will be specific to each fuzzer, the map is generic from string keys to string values. |
| 137 | + |
| 138 | +The following is an example for the fuzzer _EvoMaster_. |
| 139 | +If there is no `em.yaml` file, _EvoMaster_ generates automatically an empty configuration file `em.yaml`, where all available options are commented out. |
| 140 | +This includes the `config` object, as well as `auth` and `authTemplate`. |
| 141 | + |
| 142 | +``` |
| 143 | +### Template configuration file for EvoMaster. |
| 144 | +### Most important parameters are already present here, commented out. |
| 145 | +### Note that there are more parameters that can be configured. For a full list, see: |
| 146 | +### https://github.com/EMResearch/EvoMaster/blob/master/docs/options.md |
| 147 | +### or check them with the --help option. |
| 148 | +
|
| 149 | +
|
| 150 | +configs: {} # remove this {} when specifying properties |
| 151 | +# bbSwaggerUrl: "" |
| 152 | +# bbTargetUrl: "" |
| 153 | +# blackBox: false |
| 154 | +# configPath: "em.yaml" |
| 155 | +# endpointFocus: null |
| 156 | +# endpointPrefix: null |
| 157 | +# endpointTagFilter: null |
| 158 | +# header0: "" |
| 159 | +# header1: "" |
| 160 | +# header2: "" |
| 161 | +# maxTime: "5m" |
| 162 | +# outputFilePrefix: "EvoMaster" |
| 163 | +# outputFileSuffix: "Test" |
| 164 | +# outputFolder: "generated_tests" |
| 165 | +# outputFormat: "DEFAULT" |
| 166 | +# overrideOpenAPIUrl: "" |
| 167 | +# prematureStop: "" |
| 168 | +# ratePerMinute: 0 |
| 169 | +# sutControllerHost: "localhost" |
| 170 | +# sutControllerPort: 40100 |
| 171 | +# testTimeout: 60 |
| 172 | +
|
| 173 | +
|
| 174 | +
|
| 175 | +### Authentication configurations. |
| 176 | +### For each possible registered user, can provide an AuthenticationDto object to define how to log them in. |
| 177 | +### Different types of authentication mechanisms can be configured here. |
| 178 | +### For more information, read: https://github.com/EMResearch/EvoMaster/blob/master/docs/auth.md |
| 179 | +
|
| 180 | +#auth: |
| 181 | +# - name: ? |
| 182 | +# fixedHeaders: |
| 183 | +# - name: ? |
| 184 | +# value: ? |
| 185 | +# loginEndpointAuth: |
| 186 | +# endpoint: ? |
| 187 | +# externalEndpointURL: ? |
| 188 | +# payloadRaw: ? |
| 189 | +# payloadUserPwd: |
| 190 | +# username: ? |
| 191 | +# password: ? |
| 192 | +# usernameField: ? |
| 193 | +# passwordField: ? |
| 194 | +# verb: GET | POST |
| 195 | +# contentType: ? |
| 196 | +# token: |
| 197 | +# extractFromField: ? |
| 198 | +# httpHeaderName: ? |
| 199 | +# headerPrefix: ? |
| 200 | +# expectCookies: true | false |
| 201 | +
|
| 202 | +
|
| 203 | +### Authentication Template. |
| 204 | +### When defining auth info for several test users, lot of info might be replicated, e.g.: |
| 205 | +### endpoint: /login |
| 206 | +### verb: POST |
| 207 | +### contentType: application/json |
| 208 | +### expectCookies: true |
| 209 | +### To avoid replicating same setting over and over again, common settings can be put in a template. |
| 210 | +### When this configuration file is loaded, all fields from the template are applied to all |
| 211 | +### fields in the auth settings, unless those are not 'null' (i.e., they will not be overridden). |
| 212 | +### Note that, as names must be unique, 'name' field should not be specified in the template. |
| 213 | +
|
| 214 | +
|
| 215 | +#authTemplate: |
| 216 | +# fixedHeaders: |
| 217 | +# - name: ? |
| 218 | +# value: ? |
| 219 | +# loginEndpointAuth: |
| 220 | +# endpoint: ? |
| 221 | +# externalEndpointURL: ? |
| 222 | +# payloadRaw: ? |
| 223 | +# payloadUserPwd: |
| 224 | +# username: ? |
| 225 | +# password: ? |
| 226 | +# usernameField: ? |
| 227 | +# passwordField: ? |
| 228 | +# verb: GET | POST |
| 229 | +# contentType: ? |
| 230 | +# token: |
| 231 | +# extractFromField: ? |
| 232 | +# httpHeaderName: ? |
| 233 | +# headerPrefix: ? |
| 234 | +# expectCookies: true | false |
| 235 | +``` |
| 236 | + |
| 237 | + |
| 238 | + |
| 239 | + |
| 240 | + |
| 241 | + |
| 242 | + |
| 243 | + |
| 244 | + |
| 245 | + |
0 commit comments