github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/docs/assets/js/8.2ee33a42.js (about)

     1  (window.webpackJsonp=window.webpackJsonp||[]).push([[8],{380:function(t,a,s){"use strict";s.r(a);var e=s(25),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"authentication"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#authentication"}},[t._v("#")]),t._v(" Authentication "),s("Badge",{attrs:{text:"Since v2.5.0"}})],1),t._v(" "),s("p"),s("div",{staticClass:"table-of-contents"},[s("ul",[s("li",[s("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),s("li",[s("a",{attrs:{href:"#authenticators"}},[t._v("Authenticators")]),s("ul",[s("li",[s("a",{attrs:{href:"#basic-auth"}},[t._v("Basic Auth")])]),s("li",[s("a",{attrs:{href:"#json-web-token-jwt"}},[t._v("JSON Web Token (JWT)")])]),s("li",[s("a",{attrs:{href:"#writing-custom-authenticator"}},[t._v("Writing custom Authenticator")])])])]),s("li",[s("a",{attrs:{href:"#permissions"}},[t._v("Permissions")])])])]),s("p"),t._v(" "),s("h2",{attrs:{id:"introduction"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),s("p",[t._v("Goyave provides a convenient and expandable way of handling authentication in your application. Authentication can be enabled when registering your routes:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/auth"')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n\nauthenticator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("model"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("BasicAuthenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Authentication is handled by a simple middleware calling an "),s("strong",[t._v("Authenticator")]),t._v(". This middleware also needs a model, which will be used to fetch user information on a successful login.")]),t._v(" "),s("h4",{attrs:{id:"auth-middleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#auth-middleware"}},[t._v("#")]),t._v(" auth.Middleware")]),t._v(" "),s("p",[t._v("Middleware create a new authenticator middleware to authenticate the given model using the given authenticator.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("model interface{}")])]),t._v(" "),s("td",[s("code",[t._v("goyave.Middleware")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("authenticator Authenticator")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("authenticator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("model"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("BasicAuthenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"authenticators"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#authenticators"}},[t._v("#")]),t._v(" Authenticators")]),t._v(" "),s("p",[t._v("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.")]),t._v(" "),s("p",[s("strong",[s("code",[t._v("Authenticator")])]),t._v(" is a functional interface with a single method accepting a request and a model pointer as parameters.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Authenticate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n")])])]),s("p",[t._v("The goal of this function is to check user credentials, most of the time from the request's "),s("strong",[t._v("headers")]),t._v(". If they are correct and the user can be authenticated, the "),s("code",[t._v("user")]),t._v(" parameter is updated with the user's information. User information is most of the time fetched from the database.")]),t._v(" "),s("p",[t._v("On the other hand, if the user cannot be authenticated, the "),s("code",[t._v("Authenticate")]),t._v(" method must return an "),s("code",[t._v("error")]),t._v(' containing a localized message. For example, the error could be that the token lifetime is expired, thus "Your authentication token is expired." will be returned.')]),t._v(" "),s("p",[t._v("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 "),s("code",[t._v('auth:"username"')]),t._v(" and "),s("code",[t._v('auth:"password"')]),t._v(" tags:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" User "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tgorm"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Model\n\tEmail    "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"type:varchar(100);unique_index" auth:"username"`')]),t._v("\n\tName     "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"type:varchar(100)"`')]),t._v("\n\tPassword "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"type:varchar(60)" auth:"password"`')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),s("ul",[s("li",[t._v("The username should be "),s("strong",[t._v("unique")]),t._v(".")]),t._v(" "),s("li",[t._v("Passwords should be "),s("strong",[t._v("hashed")]),t._v(" before being stored in the database.")])]),t._v(" "),s("p",[t._v("Built-in Goyave Authenticators use "),s("a",{attrs:{href:"https://pkg.go.dev/golang.org/x/crypto/bcrypt",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("bcrypt")]),s("OutboundLink")],1),t._v(" to check if a password matches the user request.")])]),t._v(" "),s("p",[t._v("When a user is successfully authenticated on a protected route, its information is available in the controller handler, through the request "),s("code",[t._v("User")]),t._v(" field.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Hello")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tuser "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("model"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tresponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello "')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("Remember that Goyave is primarily focused on APIs. It doesn't use session nor cookies in its core features, making requests "),s("strong",[t._v("stateless")]),t._v(".")]),t._v(" "),s("p",[t._v("If you want to implement cookie or session-based authentication, be sure to protect your application from "),s("a",{attrs:{href:"https://en.wikipedia.org/wiki/Cross-site_request_forgery",target:"_blank",rel:"noopener noreferrer"}},[t._v("CSRF attacks"),s("OutboundLink")],1),t._v(".")])]),t._v(" "),s("h3",{attrs:{id:"basic-auth"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#basic-auth"}},[t._v("#")]),t._v(" Basic Auth")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://en.wikipedia.org/wiki/Basic_access_authentication",target:"_blank",rel:"noopener noreferrer"}},[t._v("Basic authentication"),s("OutboundLink")],1),t._v(" is an authentication method using the "),s("code",[t._v("Authorization")]),t._v(" header and a simple username and password combination with the following format: "),s("code",[t._v("username:password")]),t._v(", encoded in base64. There are two built-in Authenticators for Basic auth.")]),t._v(" "),s("h4",{attrs:{id:"database-provider"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#database-provider"}},[t._v("#")]),t._v(" Database provider")]),t._v(" "),s("p",[t._v("This Authenticator fetches the user information from the database, using the field tags explained earlier.")]),t._v(" "),s("p",[t._v("To apply this protection to your routes, add the following middleware:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("authenticator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("model"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("BasicAuthenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("You can then try requesting a protected route:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ curl -u username:password http://localhost:8080/hello\nHello Jérémy\n")])])]),s("h4",{attrs:{id:"config-provider"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#config-provider"}},[t._v("#")]),t._v(" Config provider")]),t._v(" "),s("p",[t._v("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.")]),t._v(" "),s("ul",[s("li",[t._v("The "),s("code",[t._v("auth.basic.username")]),t._v(" config entry defines the username that must be matched.")]),t._v(" "),s("li",[t._v("The "),s("code",[t._v("auth.basic.password")]),t._v(" config entry defines the password that must be matched.")])]),t._v(" "),s("p",[t._v("To apply this protection to your routes, start by adding the following content to your configuration:")]),t._v(" "),s("div",{staticClass:"language-json extra-class"},[s("pre",{pre:!0,attrs:{class:"language-json"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  ...\n  "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"auth"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"basic"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n      "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"username"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n      "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),t._v("\n    "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n  "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Then, add the following middleware:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ConfigBasicAuth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("The model used for this Authenticator is "),s("code",[t._v("auth.BasicUser")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" BasicUser "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tName "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("You can then try requesting a protected route:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ curl -u username:password http://localhost:8080/hello\n")])])]),s("h4",{attrs:{id:"auth-configbasicauth"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#auth-configbasicauth"}},[t._v("#")]),t._v(" auth.ConfigBasicAuth")]),t._v(" "),s("p",[t._v("Create a new authenticator middleware for config-based Basic authentication. On auth success, the request user is set to a "),s("code",[t._v("auth.BasicUser")]),t._v(".\nThe user is authenticated if the "),s("code",[t._v("auth.basic.username")]),t._v(" and "),s("code",[t._v("auth.basic.password")]),t._v(" config entries match the request's Authorization header.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td"),t._v(" "),s("td",[s("code",[t._v("goyave.Middleware")])])])])]),t._v(" "),s("h3",{attrs:{id:"json-web-token-jwt"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#json-web-token-jwt"}},[t._v("#")]),t._v(" JSON Web Token (JWT)")]),t._v(" "),s("p",[t._v("JWT, or "),s("a",{attrs:{href:"https://en.wikipedia.org/wiki/JSON_Web_Token",target:"_blank",rel:"noopener noreferrer"}},[t._v("JSON Web Token"),s("OutboundLink")],1),t._v(", 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.")]),t._v(" "),s("p",[t._v("JTW Authentication comes with two configuration entries:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("auth.jwt.expiry")]),t._v(": the number of seconds a token is valid for. Defaults to "),s("code",[t._v("300")]),t._v(" (5 minutes).")]),t._v(" "),s("li",[s("code",[t._v("auth.jwt.secret")]),t._v(": the secret used for the HMAC signature. This entry "),s("strong",[t._v("doesn't have a default value")]),t._v(", you need to define it yourself. Use a key that is "),s("strong",[t._v("at least 256 bits long")]),t._v(".")])]),t._v(" "),s("p",[t._v("To apply JWT protection to your routes, start by adding the following content to your configuration:")]),t._v(" "),s("div",{staticClass:"language-json extra-class"},[s("pre",{pre:!0,attrs:{class:"language-json"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  ...\n  "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"auth"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"jwt"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n      "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"expiry"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("300")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n      "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"secret"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"jwt-secret"')]),t._v("\n    "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n  "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Then, add the following middleware:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("authenticator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("model"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("JWTAuthenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("To request a protected route, you will need to add the following header:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("Authorization: Bearer <YOUR_TOKEN>\n")])])]),s("hr"),t._v(" "),s("p",[t._v("This Authenticator comes with a built-in login controller for password grant, using the field tags explained earlier. You can register the "),s("code",[t._v("/auth/login")]),t._v(" route using the helper function "),s("code",[t._v("auth.JTWRoutes(router)")]),t._v(".")]),t._v(" "),s("h4",{attrs:{id:"auth-jwtroutes"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#auth-jwtroutes"}},[t._v("#")]),t._v(" auth.JWTRoutes")]),t._v(" "),s("p",[t._v("Create a "),s("code",[t._v("/auth")]),t._v(" route group and registers the "),s("code",[t._v("POST /auth/login")]),t._v(" validated route. Returns the new route group.")]),t._v(" "),s("p",[t._v("Validation rules are as follows:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("username")]),t._v(": required string")]),t._v(" "),s("li",[s("code",[t._v("password")]),t._v(": required string")])]),t._v(" "),s("p",[t._v("The given model is used for username and password retrieval and for instantiating an authenticated request's user.")]),t._v(" "),s("p",[t._v("Ensure that the given router "),s("strong",[t._v("is not")]),t._v(" protected by JWT authentication, otherwise your users wouldn't be able to log in.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("router *goyave.Router")])]),t._v(" "),s("td",[s("code",[t._v("*goyave.Router")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("model interface{}")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tauth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("JWTRoutes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("model"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h4",{attrs:{id:"auth-newjwtcontroller"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#auth-newjwtcontroller"}},[t._v("#")]),t._v(" auth.NewJWTController")]),t._v(" "),s("p",[t._v("If you want or need ot register the routes yourself, you can instantiate a new JWTController using "),s("code",[t._v("auth.NewJWTController()")]),t._v(".")]),t._v(" "),s("p",[t._v("This function creates a new "),s("code",[t._v("JWTController")]),t._v(" that will be using the given model for login and token generation.")]),t._v(" "),s("p",[t._v("A "),s("code",[t._v("JWTController")]),t._v(" contains one handler called "),s("code",[t._v("Login")]),t._v(".")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("model interface{}")])]),t._v(" "),s("td",[s("code",[t._v("*auth.JWTController")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("jwtRouter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Subrouter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/auth"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\njwtRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/login"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewJWTController")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("model"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Login"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Validate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("validation"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"username"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"auth-generatetoken"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#auth-generatetoken"}},[t._v("#")]),t._v(" auth.GenerateToken")]),t._v(" "),s("p",[t._v("You may need to generate a token yourself outside of the login route. This function generates a new JWT.")]),t._v(" "),s("p",[t._v("The token is created using the HMAC SHA256 method and signed using the "),s("code",[t._v("auth.jwt.secret")]),t._v(" config entry."),s("br"),t._v("\nThe token is set to expire in the amount of seconds defined by the "),s("code",[t._v("auth.jwt.expiry")]),t._v(" config entry.")]),t._v(" "),s("p",[t._v("The generated token will contain the following claims:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("userid")]),t._v(": has the value of the "),s("code",[t._v("id")]),t._v(" parameter")]),t._v(" "),s("li",[s("code",[t._v("nbf")]),t._v(': "Not before", the current timestamp is used')]),t._v(" "),s("li",[s("code",[t._v("exp")]),t._v(': "Expriy", the current timestamp plus the '),s("code",[t._v("auth.jwt.expiry")]),t._v(" config entry.")])]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("id interface{}")])]),t._v(" "),s("td",[s("code",[t._v("string")])])]),t._v(" "),s("tr",[s("td"),t._v(" "),s("td",[s("code",[t._v("error")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("GenerateToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h3",{attrs:{id:"writing-custom-authenticator"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#writing-custom-authenticator"}},[t._v("#")]),t._v(" Writing custom Authenticator")]),t._v(" "),s("p",[t._v("The Goyave authentication system is expandable, meaning that you can implement more authentication methods by creating a new "),s("code",[t._v("Authenticator")]),t._v(".")]),t._v(" "),s("p",[t._v("The typical "),s("code",[t._v("Authenticator")]),t._v(" is an empty struct implementing the "),s("code",[t._v("Authenticator")]),t._v(" interface:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyAuthenticator "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Ensure you're correctly implementing Authenticator.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" Authenticator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("MyAuthenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implements Authenticator")]),t._v("\n")])])]),s("p",[t._v("The next step is to implement the "),s("code",[t._v("Authenticate")]),t._v(" method. Its purpose is explained at the start of this guide.")]),t._v(" "),s("p",[t._v("In this example, we are going to authenticate the user using a simple token stored in the database.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("MyAuthenticator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Authenticate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ttoken"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("BearerToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lang"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"auth.no-credentials-provided"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Find the struct field tagged with `auth:"token"`')]),t._v("\n\tcolumns "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("FindColumns")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Find the user in the database using its token")]),t._v("\n\tresult "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Where")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("columns"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('" = ?"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" errors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetErrors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("errors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("gorm"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("IsRecordNotFoundError")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Error"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Database error")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("errors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("RecordNotFound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// User not found, return "These credentials don\'t match our records."')]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lang"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"auth.invalid-credentials"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Authentication successful")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h4",{attrs:{id:"auth-findcolumns"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#auth-findcolumns"}},[t._v("#")]),t._v(" auth.FindColumns")]),t._v(" "),s("p",[t._v('Find columns in the given struct. A field matches if it has a "auth" tag with the given value.\nReturns a slice of found fields, ordered as the input '),s("code",[t._v("fields")]),t._v(" slice.")]),t._v(" "),s("p",[t._v("Promoted fields are matched as well.")]),t._v(" "),s("p",[t._v("If the nth field is not found, the nth value of the returned slice will be "),s("code",[t._v("nil")]),t._v(".")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("strct interface{}")])]),t._v(" "),s("td",[s("code",[t._v("[]*auth.Column")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("fields ...string")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Example")]),t._v(":")]),t._v(" "),s("p",[t._v("Given the following struct and "),s("code",[t._v("username")]),t._v(", "),s("code",[t._v("notatag")]),t._v(", "),s("code",[t._v("password")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" TestUser "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tgorm"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Model\n\tName     "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"type:varchar(100)"`')]),t._v("\n\tPassword "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"type:varchar(100)" auth:"password"`')]),t._v("\n\tEmail    "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"type:varchar(100);unique_index" auth:"username"`')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("fields "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("FindColumns")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"username"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"notatag"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("The result will be the "),s("code",[t._v("Email")]),t._v(" field, "),s("code",[t._v("nil")]),t._v(" and the "),s("code",[t._v("Password")]),t._v(" field.")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("Column")]),t._v(" struct is defined as follows:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Column "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tName  "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tField "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("reflect"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StructField\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]),t._v(" "),s("h2",{attrs:{id:"permissions"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#permissions"}},[t._v("#")]),t._v(" Permissions")]),t._v(" "),s("p",{staticStyle:{"text-align":"center"}},[s("img",{attrs:{src:t.$withBase("/undraw_in_progress_ql66.svg"),height:"150",alt:"In progress"}})]),t._v(" "),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),s("p",[t._v("This feature is not implemented yet and is coming in a future release.")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://github.com/System-Glitch/goyave",target:"_blank",rel:"noopener noreferrer"}},[t._v("Watch"),s("OutboundLink")],1),t._v(" the github repository to stay updated.")])])])}),[],!1,null,null,null);a.default=n.exports}}]);