github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/docs/guide/advanced/authentication.html (about)

     1  <!DOCTYPE html>
     2  <html lang="en-US">
     3    <head>
     4      <meta charset="utf-8">
     5      <meta name="viewport" content="width=device-width,initial-scale=1">
     6      <title>Authentication | Goyave</title>
     7      <meta name="generator" content="VuePress 1.5.3">
     8      <link rel="icon" type="image/png" sizes="16x16" href="/goyave/goyave_16.png">
     9      <link rel="icon" type="image/png" sizes="32x32" href="/goyave/goyave_32.png">
    10      <link rel="icon" type="image/png" sizes="64x64" href="/goyave/goyave_64.png">
    11      <link rel="icon" type="image/png" sizes="128x128" href="/goyave/goyave_128.png">
    12      <link rel="icon" type="image/png" sizes="256x256" href="/goyave/goyave_256.png">
    13      <link rel="icon" type="image/png" sizes="512x512" href="/goyave/goyave_512.png">
    14      <meta name="description" content="Goyave is a Golang web API framework aiming at cleanliness, fast development and power.">
    15      <meta name="og:title" content="Authentication - Goyave">
    16      <meta name="twitter:title" content="Authentication - Goyave">
    17      <meta name="title" content="Authentication - Goyave">
    18      <meta property="twitter:description" content="Goyave is a Golang web API framework aiming at cleanliness, fast development and power.">
    19      <meta property="twitter:image:src" content="https://system-glitch.github.io/goyave/goyave_banner.png">
    20      <meta property="twitter:card" content="summary_large_image">
    21      <meta property="og:type" content="website">
    22      <meta property="og:description" content="Goyave is a Golang web API framework aiming at cleanliness, fast development and power.">
    23      <meta property="og:image" content="https://system-glitch.github.io/goyave/goyave_banner.png">
    24      <meta property="og:site_name" content="Goyave">
    25      <link rel="preload" href="/goyave/assets/css/0.styles.589fd562.css" as="style"><link rel="preload" href="/goyave/assets/js/app.092490a7.js" as="script"><link rel="preload" href="/goyave/assets/js/4.75a9cc68.js" as="script"><link rel="preload" href="/goyave/assets/js/1.121dd9ed.js" as="script"><link rel="preload" href="/goyave/assets/js/8.2ee33a42.js" as="script"><link rel="preload" href="/goyave/assets/js/5.c83f1192.js" as="script"><link rel="prefetch" href="/goyave/assets/js/10.2f07bbf5.js"><link rel="prefetch" href="/goyave/assets/js/11.2d66fdef.js"><link rel="prefetch" href="/goyave/assets/js/12.63171b15.js"><link rel="prefetch" href="/goyave/assets/js/13.770050f3.js"><link rel="prefetch" href="/goyave/assets/js/14.b933d8cf.js"><link rel="prefetch" href="/goyave/assets/js/15.36df2a66.js"><link rel="prefetch" href="/goyave/assets/js/16.ed66719e.js"><link rel="prefetch" href="/goyave/assets/js/17.7bef5f05.js"><link rel="prefetch" href="/goyave/assets/js/18.470b55ed.js"><link rel="prefetch" href="/goyave/assets/js/19.90e0dab8.js"><link rel="prefetch" href="/goyave/assets/js/20.3a300ca3.js"><link rel="prefetch" href="/goyave/assets/js/21.c3fd6053.js"><link rel="prefetch" href="/goyave/assets/js/22.d5569617.js"><link rel="prefetch" href="/goyave/assets/js/23.931b2034.js"><link rel="prefetch" href="/goyave/assets/js/24.1a4755e7.js"><link rel="prefetch" href="/goyave/assets/js/25.0d463913.js"><link rel="prefetch" href="/goyave/assets/js/26.3c173a7a.js"><link rel="prefetch" href="/goyave/assets/js/27.9c5b36f2.js"><link rel="prefetch" href="/goyave/assets/js/28.41e055b7.js"><link rel="prefetch" href="/goyave/assets/js/29.b87adf4a.js"><link rel="prefetch" href="/goyave/assets/js/3.ef71e77d.js"><link rel="prefetch" href="/goyave/assets/js/6.2336bf0c.js"><link rel="prefetch" href="/goyave/assets/js/7.d60e55c1.js"><link rel="prefetch" href="/goyave/assets/js/9.8e043d60.js">
    26      <link rel="stylesheet" href="/goyave/assets/css/0.styles.589fd562.css">
    27    </head>
    28    <body>
    29      <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/goyave/" class="home-link router-link-active"><img src="/goyave/goyave_64.png" alt="Goyave" class="logo"> <span class="site-name can-hide">Goyave</span></a> <div class="links"><div class="user-settings"><a title="Dark theme" href="#" class="settings-button"><svg aria-hidden="true" data-prefix="fas" data-icon="cog" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg-inline--fa fa-cog fa-w-16 settings-icon"><path fill="currentColor" d="M8 0c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM8 15c-3.9 0-7-3.1-7-7 0-2.4 1.2-4.6 3.2-5.9-0.1 0.6-0.2 1.3-0.2 1.9 0 4.9 4 8.9 8.9 9-1.3 1.3-3 2-4.9 2z"></path></svg></a></div> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/goyave/guide/" class="nav-link router-link-active">
    30    Guide
    31  </a></div><div class="nav-item"><a href="https://pkg.go.dev/github.com/System-Glitch/goyave/v2" target="_blank" rel="noopener noreferrer" class="nav-link external">
    32    pkg.go.dev
    33    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <a href="https://github.com/System-Glitch/goyave" target="_blank" rel="noopener noreferrer" class="repo-link">
    34      GitHub
    35      <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/goyave/guide/" class="nav-link router-link-active">
    36    Guide
    37  </a></div><div class="nav-item"><a href="https://pkg.go.dev/github.com/System-Glitch/goyave/v2" target="_blank" rel="noopener noreferrer" class="nav-link external">
    38    pkg.go.dev
    39    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <a href="https://github.com/System-Glitch/goyave" target="_blank" rel="noopener noreferrer" class="repo-link">
    40      GitHub
    41      <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Guide</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>The Basics</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Advanced</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/goyave/guide/advanced/helpers.html" class="sidebar-link">Helpers</a></li><li><a href="/goyave/guide/advanced/authentication.html" aria-current="page" class="active sidebar-link">Authentication</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/authentication.html#introduction" class="sidebar-link">Introduction</a></li><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/authentication.html#authenticators" class="sidebar-link">Authenticators</a></li><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/authentication.html#permissions" class="sidebar-link">Permissions</a></li></ul></li><li><a href="/goyave/guide/advanced/localization.html" class="sidebar-link">Localization</a></li><li><a href="/goyave/guide/advanced/testing.html" class="sidebar-link">Testing</a></li><li><a href="/goyave/guide/advanced/multi-services.html" class="sidebar-link">Multi-services</a></li><li><a href="/goyave/guide/advanced/cors.html" class="sidebar-link">CORS</a></li><li><a href="/goyave/guide/advanced/status-handlers.html" class="sidebar-link">Status Handlers</a></li><li><a href="/goyave/guide/advanced/logging.html" class="sidebar-link">Logging</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="authentication"><a href="#authentication" class="header-anchor">#</a> Authentication <span class="badge tip" style="vertical-align:top;" data-v-15b7b770>Since v2.5.0</span></h1> <p></p><div class="table-of-contents"><ul><li><a href="#introduction">Introduction</a></li><li><a href="#authenticators">Authenticators</a><ul><li><a href="#basic-auth">Basic Auth</a></li><li><a href="#json-web-token-jwt">JSON Web Token (JWT)</a></li><li><a href="#writing-custom-authenticator">Writing custom Authenticator</a></li></ul></li><li><a href="#permissions">Permissions</a></li></ul></div><p></p> <h2 id="introduction"><a href="#introduction" class="header-anchor">#</a> Introduction</h2> <p>Goyave provides a convenient and expandable way of handling authentication in your application. Authentication can be enabled when registering your routes:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">&quot;github.com/System-Glitch/goyave/v2/auth&quot;</span>
    42  
    43  <span class="token comment">//...</span>
    44  
    45  authenticator <span class="token operator">:=</span> auth<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>model<span class="token punctuation">.</span>User<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>auth<span class="token punctuation">.</span>BasicAuthenticator<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    46  router<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span>authenticator<span class="token punctuation">)</span>
    47  </code></pre></div><p>Authentication is handled by a simple middleware calling an <strong>Authenticator</strong>. This middleware also needs a model, which will be used to fetch user information on a successful login.</p> <h4 id="auth-middleware"><a href="#auth-middleware" class="header-anchor">#</a> auth.Middleware</h4> <p>Middleware create a new authenticator middleware to authenticate the given model using the given authenticator.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td><code>model interface{}</code></td> <td><code>goyave.Middleware</code></td></tr> <tr><td><code>authenticator Authenticator</code></td> <td></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>authenticator <span class="token operator">:=</span> auth<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>model<span class="token punctuation">.</span>User<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>auth<span class="token punctuation">.</span>BasicAuthenticator<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    48  router<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span>authenticator<span class="token punctuation">)</span>
    49  </code></pre></div><h2 id="authenticators"><a href="#authenticators" class="header-anchor">#</a> Authenticators</h2> <p>This section will go into more details about Authenticators and explain the built-in ones. You will also learn how to implement an authenticator yourself.</p> <p><strong><code>Authenticator</code></strong> is a functional interface with a single method accepting a request and a model pointer as parameters.</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token function">Authenticate</span><span class="token punctuation">(</span>request <span class="token operator">*</span>goyave<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> user <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">error</span>
    50  </code></pre></div><p>The goal of this function is to check user credentials, most of the time from the request's <strong>headers</strong>. If they are correct and the user can be authenticated, the <code>user</code> parameter is updated with the user's information. User information is most of the time fetched from the database.</p> <p>On the other hand, if the user cannot be authenticated, the <code>Authenticate</code> method must return an <code>error</code> containing a localized message. For example, the error could be that the token lifetime is expired, thus &quot;Your authentication token is expired.&quot; will be returned.</p> <p>Authenticators use their model's struct fields tags to know which field to use for username and password. To make your model compatible with authentication, you must add the <code>auth:&quot;username&quot;</code> and <code>auth:&quot;password&quot;</code> tags:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> User <span class="token keyword">struct</span> <span class="token punctuation">{</span>
    51  	gorm<span class="token punctuation">.</span>Model
    52  	Email    <span class="token builtin">string</span> <span class="token string">`gorm:&quot;type:varchar(100);unique_index&quot; auth:&quot;username&quot;`</span>
    53  	Name     <span class="token builtin">string</span> <span class="token string">`gorm:&quot;type:varchar(100)&quot;`</span>
    54  	Password <span class="token builtin">string</span> <span class="token string">`gorm:&quot;type:varchar(60)&quot; auth:&quot;password&quot;`</span>
    55  <span class="token punctuation">}</span>
    56  </code></pre></div><div class="custom-block warning"><p class="custom-block-title">WARNING</p> <ul><li>The username should be <strong>unique</strong>.</li> <li>Passwords should be <strong>hashed</strong> before being stored in the database.</li></ul> <p>Built-in Goyave Authenticators use <a href="https://pkg.go.dev/golang.org/x/crypto/bcrypt" target="_blank" rel="noopener noreferrer"><code>bcrypt</code><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> to check if a password matches the user request.</p></div> <p>When a user is successfully authenticated on a protected route, its information is available in the controller handler, through the request <code>User</code> field.</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Hello</span><span class="token punctuation">(</span>response <span class="token operator">*</span>goyave<span class="token punctuation">.</span>Response<span class="token punctuation">,</span> request <span class="token operator">*</span>goyave<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    57  	user <span class="token operator">:=</span> request<span class="token punctuation">.</span>User<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>model<span class="token punctuation">.</span>User<span class="token punctuation">)</span>
    58  	response<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span>http<span class="token punctuation">.</span>StatusOK<span class="token punctuation">,</span> <span class="token string">&quot;Hello &quot;</span> <span class="token operator">+</span> user<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
    59  <span class="token punctuation">}</span>
    60  </code></pre></div><div class="custom-block tip"><p class="custom-block-title">TIP</p> <p>Remember that Goyave is primarily focused on APIs. It doesn't use session nor cookies in its core features, making requests <strong>stateless</strong>.</p> <p>If you want to implement cookie or session-based authentication, be sure to protect your application from <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery" target="_blank" rel="noopener noreferrer">CSRF attacks<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>.</p></div> <h3 id="basic-auth"><a href="#basic-auth" class="header-anchor">#</a> Basic Auth</h3> <p><a href="https://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank" rel="noopener noreferrer">Basic authentication<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> is an authentication method using the <code>Authorization</code> header and a simple username and password combination with the following format: <code>username:password</code>, encoded in base64. There are two built-in Authenticators for Basic auth.</p> <h4 id="database-provider"><a href="#database-provider" class="header-anchor">#</a> Database provider</h4> <p>This Authenticator fetches the user information from the database, using the field tags explained earlier.</p> <p>To apply this protection to your routes, add the following middleware:</p> <div class="language-go extra-class"><pre class="language-go"><code>authenticator <span class="token operator">:=</span> auth<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>model<span class="token punctuation">.</span>User<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>auth<span class="token punctuation">.</span>BasicAuthenticator<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    61  router<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span>authenticator<span class="token punctuation">)</span>
    62  </code></pre></div><p>You can then try requesting a protected route:</p> <div class="language- extra-class"><pre class="language-text"><code>$ curl -u username:password http://localhost:8080/hello
    63  Hello Jérémy
    64  </code></pre></div><h4 id="config-provider"><a href="#config-provider" class="header-anchor">#</a> Config provider</h4> <p>This Authenticator fetches the user information from the config. This method is good for quick proof-of-concepts, as it requires minimum setup, but shouldn't be used in real-world applications.</p> <ul><li>The <code>auth.basic.username</code> config entry defines the username that must be matched.</li> <li>The <code>auth.basic.password</code> config entry defines the password that must be matched.</li></ul> <p>To apply this protection to your routes, start by adding the following content to your configuration:</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span>
    65    ...
    66    <span class="token property">&quot;auth&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    67      <span class="token property">&quot;basic&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    68        <span class="token property">&quot;username&quot;</span><span class="token operator">:</span> <span class="token string">&quot;admin&quot;</span><span class="token punctuation">,</span>
    69        <span class="token property">&quot;password&quot;</span><span class="token operator">:</span> <span class="token string">&quot;admin&quot;</span>
    70      <span class="token punctuation">}</span>
    71    <span class="token punctuation">}</span>
    72  <span class="token punctuation">}</span>
    73  </code></pre></div><p>Then, add the following middleware:</p> <div class="language-go extra-class"><pre class="language-go"><code>router<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span>auth<span class="token punctuation">.</span><span class="token function">ConfigBasicAuth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    74  </code></pre></div><p>The model used for this Authenticator is <code>auth.BasicUser</code>:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> BasicUser <span class="token keyword">struct</span> <span class="token punctuation">{</span>
    75  	Name <span class="token builtin">string</span>
    76  <span class="token punctuation">}</span>
    77  </code></pre></div><p>You can then try requesting a protected route:</p> <div class="language- extra-class"><pre class="language-text"><code>$ curl -u username:password http://localhost:8080/hello
    78  </code></pre></div><h4 id="auth-configbasicauth"><a href="#auth-configbasicauth" class="header-anchor">#</a> auth.ConfigBasicAuth</h4> <p>Create a new authenticator middleware for config-based Basic authentication. On auth success, the request user is set to a <code>auth.BasicUser</code>.
    79  The user is authenticated if the <code>auth.basic.username</code> and <code>auth.basic.password</code> config entries match the request's Authorization header.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td></td> <td><code>goyave.Middleware</code></td></tr></tbody></table> <h3 id="json-web-token-jwt"><a href="#json-web-token-jwt" class="header-anchor">#</a> JSON Web Token (JWT)</h3> <p>JWT, or <a href="https://en.wikipedia.org/wiki/JSON_Web_Token" target="_blank" rel="noopener noreferrer">JSON Web Token<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>, is an open standard of authentication that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. Goyave uses HMAC-SHA256 in its implementation.</p> <p>JTW Authentication comes with two configuration entries:</p> <ul><li><code>auth.jwt.expiry</code>: the number of seconds a token is valid for. Defaults to <code>300</code> (5 minutes).</li> <li><code>auth.jwt.secret</code>: the secret used for the HMAC signature. This entry <strong>doesn't have a default value</strong>, you need to define it yourself. Use a key that is <strong>at least 256 bits long</strong>.</li></ul> <p>To apply JWT protection to your routes, start by adding the following content to your configuration:</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span>
    80    ...
    81    <span class="token property">&quot;auth&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    82      <span class="token property">&quot;jwt&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    83        <span class="token property">&quot;expiry&quot;</span><span class="token operator">:</span> <span class="token number">300</span><span class="token punctuation">,</span>
    84        <span class="token property">&quot;secret&quot;</span><span class="token operator">:</span> <span class="token string">&quot;jwt-secret&quot;</span>
    85      <span class="token punctuation">}</span>
    86    <span class="token punctuation">}</span>
    87  <span class="token punctuation">}</span>
    88  </code></pre></div><p>Then, add the following middleware:</p> <div class="language-go extra-class"><pre class="language-go"><code>authenticator <span class="token operator">:=</span> auth<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>model<span class="token punctuation">.</span>User<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>auth<span class="token punctuation">.</span>JWTAuthenticator<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    89  router<span class="token punctuation">.</span><span class="token function">Middleware</span><span class="token punctuation">(</span>authenticator<span class="token punctuation">)</span>
    90  </code></pre></div><p>To request a protected route, you will need to add the following header:</p> <div class="language- extra-class"><pre class="language-text"><code>Authorization: Bearer &lt;YOUR_TOKEN&gt;
    91  </code></pre></div><hr> <p>This Authenticator comes with a built-in login controller for password grant, using the field tags explained earlier. You can register the <code>/auth/login</code> route using the helper function <code>auth.JTWRoutes(router)</code>.</p> <h4 id="auth-jwtroutes"><a href="#auth-jwtroutes" class="header-anchor">#</a> auth.JWTRoutes</h4> <p>Create a <code>/auth</code> route group and registers the <code>POST /auth/login</code> validated route. Returns the new route group.</p> <p>Validation rules are as follows:</p> <ul><li><code>username</code>: required string</li> <li><code>password</code>: required string</li></ul> <p>The given model is used for username and password retrieval and for instantiating an authenticated request's user.</p> <p>Ensure that the given router <strong>is not</strong> protected by JWT authentication, otherwise your users wouldn't be able to log in.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td><code>router *goyave.Router</code></td> <td><code>*goyave.Router</code></td></tr> <tr><td><code>model interface{}</code></td> <td></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Register</span><span class="token punctuation">(</span>router <span class="token operator">*</span>goyave<span class="token punctuation">.</span>Router<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    92  	auth<span class="token punctuation">.</span><span class="token function">JWTRoutes</span><span class="token punctuation">(</span>router<span class="token punctuation">,</span> <span class="token operator">&amp;</span>model<span class="token punctuation">.</span>User<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    93  <span class="token punctuation">}</span>
    94  </code></pre></div><h4 id="auth-newjwtcontroller"><a href="#auth-newjwtcontroller" class="header-anchor">#</a> auth.NewJWTController</h4> <p>If you want or need ot register the routes yourself, you can instantiate a new JWTController using <code>auth.NewJWTController()</code>.</p> <p>This function creates a new <code>JWTController</code> that will be using the given model for login and token generation.</p> <p>A <code>JWTController</code> contains one handler called <code>Login</code>.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td><code>model interface{}</code></td> <td><code>*auth.JWTController</code></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>jwtRouter <span class="token operator">:=</span> router<span class="token punctuation">.</span><span class="token function">Subrouter</span><span class="token punctuation">(</span><span class="token string">&quot;/auth&quot;</span><span class="token punctuation">)</span>
    95  jwtRouter<span class="token punctuation">.</span><span class="token function">Route</span><span class="token punctuation">(</span><span class="token string">&quot;POST&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;/login&quot;</span><span class="token punctuation">,</span> auth<span class="token punctuation">.</span><span class="token function">NewJWTController</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>model<span class="token punctuation">.</span>User<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Login<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Validate</span><span class="token punctuation">(</span>validation<span class="token punctuation">.</span>RuleSet<span class="token punctuation">{</span>
    96  	<span class="token string">&quot;username&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">&quot;required&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;string&quot;</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    97  	<span class="token string">&quot;password&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">&quot;required&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;string&quot;</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    98  <span class="token punctuation">}</span><span class="token punctuation">)</span>
    99  </code></pre></div><h4 id="auth-generatetoken"><a href="#auth-generatetoken" class="header-anchor">#</a> auth.GenerateToken</h4> <p>You may need to generate a token yourself outside of the login route. This function generates a new JWT.</p> <p>The token is created using the HMAC SHA256 method and signed using the <code>auth.jwt.secret</code> config entry.<br>
   100  The token is set to expire in the amount of seconds defined by the <code>auth.jwt.expiry</code> config entry.</p> <p>The generated token will contain the following claims:</p> <ul><li><code>userid</code>: has the value of the <code>id</code> parameter</li> <li><code>nbf</code>: &quot;Not before&quot;, the current timestamp is used</li> <li><code>exp</code>: &quot;Expriy&quot;, the current timestamp plus the <code>auth.jwt.expiry</code> config entry.</li></ul> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td><code>id interface{}</code></td> <td><code>string</code></td></tr> <tr><td></td> <td><code>error</code></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>token<span class="token punctuation">,</span> err <span class="token operator">:=</span> auth<span class="token punctuation">.</span><span class="token function">GenerateToken</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>ID<span class="token punctuation">)</span>
   101  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
   102  	<span class="token function">panic</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
   103  <span class="token punctuation">}</span>
   104  fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span>
   105  </code></pre></div><h3 id="writing-custom-authenticator"><a href="#writing-custom-authenticator" class="header-anchor">#</a> Writing custom Authenticator</h3> <p>The Goyave authentication system is expandable, meaning that you can implement more authentication methods by creating a new <code>Authenticator</code>.</p> <p>The typical <code>Authenticator</code> is an empty struct implementing the <code>Authenticator</code> interface:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> MyAuthenticator <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
   106  
   107  <span class="token comment">// Ensure you're correctly implementing Authenticator.</span>
   108  <span class="token keyword">var</span> <span class="token boolean">_</span> Authenticator <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token operator">*</span>MyAuthenticator<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span> <span class="token comment">// implements Authenticator</span>
   109  </code></pre></div><p>The next step is to implement the <code>Authenticate</code> method. Its purpose is explained at the start of this guide.</p> <p>In this example, we are going to authenticate the user using a simple token stored in the database.</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>MyAuthenticator<span class="token punctuation">)</span> <span class="token function">Authenticate</span><span class="token punctuation">(</span>request <span class="token operator">*</span>goyave<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> user <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
   110  	token<span class="token punctuation">,</span> ok <span class="token operator">:=</span> request<span class="token punctuation">.</span><span class="token function">BearerToken</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
   111  
   112  	<span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span>
   113  		<span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span>lang<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>Lang<span class="token punctuation">,</span> <span class="token string">&quot;auth.no-credentials-provided&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
   114  	<span class="token punctuation">}</span>
   115  
   116  	<span class="token comment">// Find the struct field tagged with `auth:&quot;token&quot;`</span>
   117  	columns <span class="token operator">:=</span> auth<span class="token punctuation">.</span><span class="token function">FindColumns</span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> <span class="token string">&quot;token&quot;</span><span class="token punctuation">)</span>
   118  
   119  	<span class="token comment">// Find the user in the database using its token</span>
   120  	result <span class="token operator">:=</span> database<span class="token punctuation">.</span><span class="token function">GetConnection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>columns<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>Name<span class="token operator">+</span><span class="token string">&quot; = ?&quot;</span><span class="token punctuation">,</span> token<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">First</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span>
   121  
   122  	<span class="token keyword">if</span> errors <span class="token operator">:=</span> result<span class="token punctuation">.</span><span class="token function">GetErrors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">len</span><span class="token punctuation">(</span>errors<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>gorm<span class="token punctuation">.</span><span class="token function">IsRecordNotFoundError</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>Error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
   123  		<span class="token comment">// Database error</span>
   124  		<span class="token function">panic</span><span class="token punctuation">(</span>errors<span class="token punctuation">)</span>
   125  	<span class="token punctuation">}</span>
   126  
   127  	<span class="token keyword">if</span> result<span class="token punctuation">.</span><span class="token function">RecordNotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   128  		<span class="token comment">// User not found, return &quot;These credentials don't match our records.&quot;</span>
   129  		<span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span>lang<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>Lang<span class="token punctuation">,</span> <span class="token string">&quot;auth.invalid-credentials&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
   130  	<span class="token punctuation">}</span>
   131  
   132  	<span class="token comment">// Authentication successful</span>
   133  	<span class="token keyword">return</span> <span class="token boolean">nil</span>
   134  <span class="token punctuation">}</span>
   135  </code></pre></div><h4 id="auth-findcolumns"><a href="#auth-findcolumns" class="header-anchor">#</a> auth.FindColumns</h4> <p>Find columns in the given struct. A field matches if it has a &quot;auth&quot; tag with the given value.
   136  Returns a slice of found fields, ordered as the input <code>fields</code> slice.</p> <p>Promoted fields are matched as well.</p> <p>If the nth field is not found, the nth value of the returned slice will be <code>nil</code>.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td><code>strct interface{}</code></td> <td><code>[]*auth.Column</code></td></tr> <tr><td><code>fields ...string</code></td> <td></td></tr></tbody></table> <p><strong>Example</strong>:</p> <p>Given the following struct and <code>username</code>, <code>notatag</code>, <code>password</code>:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> TestUser <span class="token keyword">struct</span> <span class="token punctuation">{</span>
   137  	gorm<span class="token punctuation">.</span>Model
   138  	Name     <span class="token builtin">string</span> <span class="token string">`gorm:&quot;type:varchar(100)&quot;`</span>
   139  	Password <span class="token builtin">string</span> <span class="token string">`gorm:&quot;type:varchar(100)&quot; auth:&quot;password&quot;`</span>
   140  	Email    <span class="token builtin">string</span> <span class="token string">`gorm:&quot;type:varchar(100);unique_index&quot; auth:&quot;username&quot;`</span>
   141  <span class="token punctuation">}</span>
   142  </code></pre></div><div class="language-go extra-class"><pre class="language-go"><code>fields <span class="token operator">:=</span> auth<span class="token punctuation">.</span><span class="token function">FindColumns</span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> <span class="token string">&quot;username&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;notatag&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;password&quot;</span><span class="token punctuation">)</span>
   143  </code></pre></div><p>The result will be the <code>Email</code> field, <code>nil</code> and the <code>Password</code> field.</p> <div class="custom-block tip"><p class="custom-block-title">TIP</p> <p>The <code>Column</code> struct is defined as follows:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Column <span class="token keyword">struct</span> <span class="token punctuation">{</span>
   144  	Name  <span class="token builtin">string</span>
   145  	Field <span class="token operator">*</span>reflect<span class="token punctuation">.</span>StructField
   146  <span class="token punctuation">}</span>
   147  </code></pre></div></div> <h2 id="permissions"><a href="#permissions" class="header-anchor">#</a> Permissions</h2> <p style="text-align:center;"><img src="/goyave/undraw_in_progress_ql66.svg" height="150" alt="In progress"></p> <div class="custom-block warning"><p class="custom-block-title">WARNING</p> <p>This feature is not implemented yet and is coming in a future release.</p> <p><a href="https://github.com/System-Glitch/goyave" target="_blank" rel="noopener noreferrer">Watch<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> the github repository to stay updated.</p></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/System-Glitch/goyave/edit/master/docs_src/src/guide/advanced/authentication.md" target="_blank" rel="noopener noreferrer">Edit this page on GitHub</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
   148        ←
   149        <a href="/goyave/guide/advanced/helpers.html" class="prev">
   150          Helpers
   151        </a></span> <span class="next"><a href="/goyave/guide/advanced/localization.html">
   152          Localization
   153        </a>
   154        →
   155      </span></p></div> </main></div><div class="global-ui"><!----></div></div>
   156      <script src="/goyave/assets/js/app.092490a7.js" defer></script><script src="/goyave/assets/js/4.75a9cc68.js" defer></script><script src="/goyave/assets/js/1.121dd9ed.js" defer></script><script src="/goyave/assets/js/8.2ee33a42.js" defer></script><script src="/goyave/assets/js/5.c83f1192.js" defer></script>
   157    </body>
   158  </html>