CORS

If you are having trouble authenticating with your application from an SPA that executes on a separate subdomain, you have likely misconfigured your CORS (Cross-Origin Resource Sharing) or session cookie settings.

For more information on CORS and CORS headers, please consult the MDN web documentation on CORS.

You should ensure that your application's CORS configuration is returning the Access-Control-Allow-Credentials header with a value of true by setting the AllowCredentials option within your cors middleware configuration to true.

In addition, you should enable the withCredentials option on your global axios instance:

axios.defaults.withCredentials = true;

Using the CORS middleware

In this section you will learn how to use this middleware to allow cross-origin resource sharing.

The CORS middleware source code is located at iris-contrib/middleware repository.

1. Install the middleware:

$ go get github.com/iris-contrib/middleware/jwt@master

2. Import in your code:

import "github.com/iris-contrib/middleware/cors"

3. Initialize and configurate the middleware:

crs := cors.New(cors.Options{
    AllowedOrigins:   []string{"*"},
    AllowCredentials: true,
})

4. Register the middleware:

app.UseRouter(crs)

That's all. Your Iris web server can now accept cross-origin API requests from your client.

Example of a raw Javascript Client:

// Replace the "host" with your Iris web server's domain.
const host = 'https://e1de7bc1.ngrok.io';

async function postData(url = '', data = {}) {
    const response = await fetch(url, {
        method: 'POST',
        mode: 'cors',
        cache: 'no-cache',
        credentials: 'same-origin',
        headers: {
            'Content-Type': 'application/json'
        },
        redirect: 'follow',
        referrerPolicy: 'no-referrer',
        body: JSON.stringify(data)
    });
    return response.json();
}

postData(host + '/api/mailer', {
        email: "me@test.com"
    })
    .then(data => {
        console.log(data);
        document.write(data.message);
    });

Full example code can be found at: iris-contrib/middleware/cors/_example.

The CORS Configuration

The full configuration of the cors.Options struct looks like this:

// AllowedOrigins is a list of origins a cross-domain
// request can be executed from.
// If the special "*" value is present in the list,
// all origins will be allowed.
// An origin may contain a wildcard (*) to replace 0
// or more characters (i.e.: http://*.domain.com).
// Usage of wildcards implies a small performance penalty.
// Only one wildcard can be used per origin.
// Default value is ["*"].
AllowedOrigins []string

// AllowOriginFunc is a custom function to validate the origin.
// It takes the origin as argument and returns true if allowed
// or false otherwise. If this option is
// set, the content of AllowedOrigins is ignored.
AllowOriginFunc func(origin string) bool

// AllowedMethods is a list of methods the
// client is allowed to use with cross-domain requests.
// Default value is simple methods (HEAD, GET and POST).
AllowedMethods []string

// AllowedHeaders is list of non simple headers
// the client is allowed to use with
// cross-domain requests.
// If the special "*" value is present in the list,
// all headers will be allowed.
// Default value is [] but "Origin" is always
// appended to the list.
AllowedHeaders []string

// ExposedHeaders indicates which headers are safe to
// expose to the API of a CORS API specification.
ExposedHeaders []string

// MaxAge indicates how long (in seconds) the results
// of a preflight request can be cached.
MaxAge int

// AllowCredentials indicates whether the request
// can include user credentials like
// cookies, HTTP authentication
// or client side SSL certificates.
AllowCredentials bool

// OptionsPassthrough instructs preflight to
// let other potential next handlers to
// process the OPTIONS method. Turn this on
// if your application handles OPTIONS.
OptionsPassthrough bool

// Debugging flag adds additional output to
// debug server side CORS issues.
Debug bool

Do it yourself

You can always use the Iris request Context to manually send the necessary headers to handle preflight and therefore allow cross-origin requests.

Here is a simple example:

package main

import "github.com/kataras/iris/v12"

func main() {
	app := iris.New()

    // Our custom CORS middleware.
	crs := func(ctx iris.Context) {
		ctx.Header("Access-Control-Allow-Origin", "*")
		ctx.Header("Access-Control-Allow-Credentials", "true")

		if ctx.Method() == iris.MethodOptions {
            ctx.Header("Access-Control-Methods",
                "POST, PUT, PATCH, DELETE")

            ctx.Header("Access-Control-Allow-Headers",
                "Access-Control-Allow-Origin,Content-Type")

            ctx.Header("Access-Control-Max-Age",
                "86400")

			ctx.StatusCode(iris.StatusNoContent)
			return
		}

		ctx.Next()
	}

    app.UseRouter(crs)
    
    // [register routes...]
}

Last updated