Skip to content

Commit

Permalink
Update amp-form docs and add an expanded note on CORS security. (#4485)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkhatib authored Aug 17, 2016
1 parent 5b10439 commit 216c45f
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 0 deletions.
102 changes: 102 additions & 0 deletions extensions/amp-form/amp-form.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,109 @@ __required__

Action must be provided, `https` and is non-cdn link (does **NOT** link to https://cdn.ampproject.org).

**action-xhr**
__(optional)__
You can also provide an action-xhr attribute, if provided, the form will be submitted in an XHR fashion.

This attribute can be the same or a different endpoint than `action` and has the same action requirements above.

**Important**: Your XHR endpoints need to follow and implement [CORS Requests in AMP spec](https://github.com/ampproject/amphtml/blob/master/spec/amp-cors-requests.md).

All other [form attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) are optional.

## Inputs
Currently, `<input type=button>`, `<input type=file>`, `<input type=image>` and `<input type=password>` are not allowed. (This might be reconsidered in the future - please let us know if you require these and use cases).

## Events
`amp-form` exposes 3 events:

* **submit**
Emitted whenever the form is submitted and before the submission is complete.

* **submit-success**
Emitted whenever the form submission is done and response is a success.

* **submit-error**
Emitted whenever the form submission is done and response is an error.

These events can be used through the [`on` attribute](https://github.com/ampproject/amphtml/blob/master/spec/amp-html-format.md#on).
For example, the following listens to both `submit-success` and `submit-error` and shows different lightboxes depending on the event.

```html
<form ... on="submit-success:success-lightbox;submit-error:error-lightbox" ...>
</form>
```

See the [full example here](https://github.com/ampproject/amphtml/blob/master/examples/forms.amp.html).

## Success/Error Response Rendering
`amp-form` allows publishers to render the responses using [Extended Templates](https://github.com/ampproject/amphtml/blob/master/spec/amp-html-format.md#extended-templates).

Using `submit-success` and `submit-error` special marker attributes, publishers can mark any **child element of form** and include a `<template></template>` tag inside it to render the response in it.

The response is expected to be a valid JSON Object. For example, if the publisher's `action-xhr` endpoint returns the following responses:

**Success Response**
```json
{
"name": "Jane Miller",
"interests": [{"name": "Basketball"}, {"name": "Swimming"}, {"name": "Reading"}],
"email": "[email protected]"
}
```

**Error Response**
```json
{
"name": "Jane Miller",
"message": "The email ([email protected]) you used is already subscribed."
}
```

Publishers can render these in a template inside their forms as follows.

```html
<form ...>
<fieldset>
...
</fieldset>
<div submit-success>
<template type="amp-mustache">
Success! Thanks {{name}} for subscribing! Please make sure to check your email {{email}}
to confirm! After that we'll start sending you weekly articles on {{#interests}}<b>{{name}}</b> {{/interests}}.
</template>
</div>
<div submit-error>
<template type="amp-mustache">
Oops! {{name}}, {{message}}.
</template>
</div>
</form>
```

See the [full example here](https://github.com/ampproject/amphtml/blob/master/examples/forms.amp.html).

## Polyfills
`amp-form` provide polyfills for behaviors and functionality missing from some browsers or being implemented in the next version of CSS.

#### Invalid Submit Blocking and Validation Message Bubble
Browsers that uses webkit-based engines currently (as of August 2016) do not support invalid form submissions. These include Safari on all platforms, and all iOS browsers. `amp-form` polyfills this behavior to block any invalid submissions and show validation message bubbles on invalid inputs.

**Note**: Messages are sometimes limited to a few words like "required field", these messages are provided by the browser implementation. We'll be working on allowing publisher-provided custom validation messages as well as custom validation UIs (instead of the builtin/polyfill'd bubbles).

#### :user-invalid/:user-valid
These pseudo classes are part of the [future CSS Selectors 4 spec](https://drafts.csswg.org/selectors-4/#user-pseudos) and are introduced to allow better hooks for styling invalid/valid fields based on a few criteria.

One of the main differences between `:invalid` and `:user-invalid` is when are they applied to the element. :user-invalid is applied after a significant interaction from the user with the field (e.g. user types in a field, or blur from the field).

`amp-form` provides classes (see below) to polyfill these pseudo-classes. `amp-form` also propagates these to ancestors `fieldset`s and `form`.


## Classes and CSS Hooks
`amp-form` provides classes and CSS hooks for publishers to style their forms and inputs.

`.amp-form-submitting`, `.amp-form-submit-success` and `.amp-form-submit-error` are added to indicate the state of the form submission.

`.user-valid` and `.user-invalid` classes are a polyfill for the pseudo classes as described above. Publishers can use these to style their inputs and fieldsets to be responsive to user actions (e.g. highlighting an invalid input with a red border after user blurs from it).

See the [full example here](https://github.com/ampproject/amphtml/blob/master/examples/forms.amp.html) on using these.
8 changes: 8 additions & 0 deletions spec/amp-cors-requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,11 @@ The resulting HTTP response has to also contain the following headers:
- `Access-Control-Allow-Origin: <origin>`. Here "origin" refers to the requesting origin that was allowed via "Origin" request header above. Ex: "https://cdn.ampproject.org". This is a CORS spec requirement. Notice that while CORS spec allows the value of '\*' to be returned in this header, AMP strongly discourages use of '\*'. Instead the value of the "Origin" header should be validated and echoed for improved security.
- `AMP-Access-Control-Allow-Source-Origin: <source-origin>`. Here "source-origin" indicates the source origin that is allowed to read the authorization response as was verified via "__amp_source_origin" URL parameter. Ex: "https://publisher1.com".
- `Access-Control-Expose-Headers: AMP-Access-Control-Allow-Source-Origin`. This header simply allows CORS response to contain the "AMP-Access-Control-Allow-Source-Origin" header.

#### Note on non-idempotent Requests
When making CORS requests that would change the state of your system (e.g. uer subscribes to or unsubscribes from a mailing list) the first two steps you need to make sure to do:

1. Check the `Origin` header. If the origin was not `*.ampproject.org` or the publisher's origin, stop and return an error response.
2. Check the `__amp_source_origin` query parameter. If it's not the publisher's origin stop and return an error response.

It's very important that these are done first before processing the request, this provides protection against CSRF attacks and avoids processing untrusted sources requests.

0 comments on commit 216c45f

Please sign in to comment.