1"use strict";(self.webpackChunkapiato_documentation=self.webpackChunkapiato_documentation||[]).push([[13837],{13925:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"core-features/authentication","title":"Authentication","description":"- API Authentication (OAuth 2.0)","source":"@site/versioned_docs/version-10.x/core-features/authentication.md","sourceDirName":"core-features","slug":"/core-features/authentication","permalink":"/docs/10.x/core-features/authentication","draft":false,"unlisted":false,"editUrl":"https://github.com/apiato/documentation/tree/master/versioned_docs/version-10.x/core-features/authentication.md","tags":[],"version":"10.x","lastUpdatedBy":"Mohammad Alavi","lastUpdatedAt":1724505926000,"frontMatter":{"title":"Authentication"},"sidebar":"docs","previous":{"title":"Code Generator","permalink":"/docs/10.x/core-features/code-generator"},"next":{"title":"Authorization","permalink":"/docs/10.x/core-features/authorization"}}');var s=t(74848),r=t(28453);const o={title:"Authentication"},a=void 0,c={},l=[{value:"API Authentication (OAuth 2.0)",id:"api-authentication-oauth-20",level:2},{value:"How to get Access Token using OAuth 2.0",id:"how-to-get-access-token-using-oauth-20",level:2},{value:"Quick Overview",id:"quick-overview",level:2},{value:"A: For first-party clients",id:"first-party-clients",level:2},{value:"Login with Proxy for first-party clients",id:"login-with-proxy-for-first-party-clients",level:3},{value:"Login without Proxy for first-party clients",id:"login-without-proxy-for-first-party-clients",level:3},{value:"B: For third-party clients",id:"third-party-clients",level:2},{value:"Login without Proxy for third-party clients",id:"login-without-proxy-for-third-party-clients",level:3},{value:"Login With Custom Attributes",id:"login-with-custom-attributes",level:2},{value:"Logout",id:"logout",level:2},{value:"Responses",id:"responses",level:2},{value:"Change Tokens Expiration dates",id:"change-tokens-expiration-dates",level:2},{value:"Web Authentication",id:"web-authentication",level:2},{value:"Refresh Token",id:"refresh-token",level:2},{value:"Refresh Token with proxy for first-party clients",id:"refresh-token-with-proxy-for-first-party-clients",level:3},{value:"Refresh Token without proxy for first-party or third-party clients",id:"refresh-token-without-proxy-for-first-party-or-third-party-clients",level:3},{value:"Force Email Confirmation",id:"force-email-confirmation",level:2},{value:"Reset Password",id:"reset-password",level:2},{value:"Social Authentication",id:"social-authentication",level:2}];function h(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#api-authentication-oauth-20",children:"API Authentication (OAuth 2.0)"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#how-to-get-access-token-using-oauth-20",children:"How to get Access Token using OAuth 2.0"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#quick-overview",children:"Quick Overview"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#first-party-clients",children:"A: For first-party clients"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#login-with-proxy-for-first-party-clients",children:"Login with Proxy for first-party clients"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#login-without-proxy-for-first-party-clients",children:"Login without Proxy for first-party clients"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#third-party-clients",children:"B: For third-party clients"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#login-without-proxy-for-third-party-clients",children:"Login without Proxy for third-party clients"})}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#login-with-custom-attributes",children:"Login With Custom Attributes"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#logout",children:"Logout"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#responses",children:"Responses"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#change-tokens-expiration-dates",children:"Change Tokens Expiration dates"})}
1),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#web-authentication",children:"Web Authentication"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#refresh-token",children:"Refresh Token"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#refresh-token-with-proxy-for-first-party-clients",children:"Refresh Token with proxy for first-party clients"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#refresh-token-without-proxy-for-first-party-or-third-party-clients",children:"Refresh Token without proxy for first-party or third-party clients"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#force-email-confirmation",children:"Force Email Confirmation"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#reset-password",children:"Reset Password"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#social-authentication",children:"Social Authentication"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Middlewares are the best solution to apply Authentication in your Ap
1p."}),"\n",(0,s.jsxs)(n.p,{children:["In Apiato you can use these two ",(0,s.jsx)(n.code,{children:"Authentication Middlewares"}),", to protect your endpoints:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["API Authentication: ",(0,s.jsx)(n.code,{children:"auth:api"})]}),"\n",(0,s.jsxs)(n.li,{children:["Web Authentication: ",(0,s.jsx)(n.code,{children:"auth:web"})]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"api-authentication-oauth-20",children:"API Authentication (OAuth 2.0)"}),"\n",(0,s.jsxs)(n.p,{children:["To protect an ",(0,s.jsx)(n.strong,{children:"API"})," Endpoint from being accessible by unauthenticated users you can use the ",(0,s.jsx)(n.code,{children:"auth:api"})," Middleware."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-php",children:"Route::get('secret/info', [Controller::class, 'getSecretInfo'])\n ->middleware('auth:api');\n"})}),"\n",(0,s.jsxs)(n.p,{children:["All Endpoints protected with ",(0,s.jsx)(n.code,{children:"auth:api"})," are accessible only when sending them a valid access token."]}),"\n",(0,s.jsxs)(n.p,{children:["This Middleware is provided by the ",(0,s.jsx)(n.a,{href:"https://laravel.com/docs/passport",children:"Laravel Passport"})," package. So you can read its\ndocumentation for more details."]}),"\n",(0,s.jsx)(n.h2,{id:"how-to-get-access-token-using-oauth-20",children:"How to get Access Token using OAuth 2.0"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Generate ",(0,s.jsx)(n.code,{children:"client_id"})," & ",(0,s.jsx)(n.code,{children:"client_secret"}),". (",(0,s.jsx)(n.a,{href:"#first-party-clients",children:"more details"}),")"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Use the generated client to call this oauth/token endpoint ",(0,s.jsx)(n.code,{children:"http://api.apiato.test/v1/oauth/token"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["All the Auth Endpoints are documented. Go to ",(0,s.jsx)(n.a,{href:"../additional-features/apiato-containers/documentation",children:"Documentation Generator Page"}),"\nto see how you can generate the API documentation, and read them."]}),"\n",(0,s.jsx)(n.h2,{id:"quick-overview",children:"Quick Overview"}),"\n",(0,s.jsxs)(n.p,{children:["OAuth lets you authenticate using different methods, these methods are called ",(0,s.jsx)(n.code,{children:"grants"}),".\nFor how to decide which grant type you should use, check ",(0,s.jsx)(n.a,{href:"https://oauth2.thephpleague.com/authorization-server/which-grant/",children:"this"}),"\nand keep reading this documentation."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Definitions:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The Client credentials: are the ",(0,s.jsx)(n.code,{children:"client_id"})," & ",(0,s.jsx)(n.code,{children:"client_secret"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["The Proxy: is just an endpoint, that you should call instead of calling the Auth server endpoints directly, the proxy\nendpoint will append the client credentials to your request and calls the Auth server for you, then return its response back. Each first-party client app should have its own proxy endpoints (at least one for each Login and Token Refresh). By default, Apiato provide a ",(0,s.jsx)(n.code,{children:"Web Client"})," proxy endpoint."]}),"\n"]}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"You can Log in to the first party app with proxy or without proxy, while for the third party you only need to log in\nwithout proxy. (same apply to refreshing token)."}),"\n",(0,s.jsx)(n.p,{children:"For first party apps:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"With Proxy < best and easiest way, (requires manually generating clients creating proxy endpoints for each client)"}),"\n",(0,s.jsx)(n.li,{children:"Without Proxy < if your frontend is not exposing the client credentials, you can call the Auth server endpoints directly without proxy."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"For third party apps:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Without Proxy < you don't need a proxy for the third party clients as they usually integrate with your API from the backend side which protects the client credentials."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"first-party-clients",children:"A: For first-party clients"}),"\n",(0,s.jsx)(n.p,{children:"First-party clients (Your Frontend Mobile, Web,... Apps) usually consumes your private API (Internal API)."}),"\n",(0,s.jsxs)(n.p,{children:["For first-party clients you need to use the ",(0,s.jsx)(n.strong,{children:"Resource owner credentials grant"})," (A.K.A. Password Grant Tokens)."]}),"\n",(0,s.jsx)(n.p,{children:"When this grant type is used, your server needs to authenticate the Client App first (ensuring the request is coming\nfrom your trusted frontend App) and then needs to check if the user credentials are correct (ensuring the user is\nregistered and has the right access), before issuing an access token."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Note:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"On register: the API returns user data. You will need to log that user in (using the same credentials he passed) to\nget his Access Token and make other API calls."}),"\n",(0,s.jsx)(n.li,{children:"On login: the API returns the user Access Token with Refresh Token. You will need to request the User data by making\nanother call to the user endpoint, using his Access Token."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"How it works:"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Create a password type Client in your database to represent one of your Apps (ex: Mobile App). Use\n",(0,s.jsx)(n.code,{children:"php artisan passport:client --password"})," to generate the client."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"After registration, the user can enter his (username + password) in your Ap
1p login screen."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Your App should send a ",(0,s.jsx)(n.strong,{children:"Post"})," request to ",(0,s.jsx)(n.code,{children:"http://api.apiato.test/v1/oauth/token"})," containing the user credentials\n(",(0,s.jsx)(n.code,{children:"username"})," and ",(0,s.jsx)(n.code,{children:"password"}),") and the client credentials (",(0,s.jsx)(n.code,{children:"client_id"})," and ",(0,s.jsx)(n.code,{children:"client_secret"}),") in addition to the ",(0,s.jsx)(n.code,{children:"scope"}),"\nand ",(0,s.jsx)(n.code,{children:"grant_type=password"}),":"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Request:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"curl --request POST \\\n --url http://api.apiato.test/v1/oauth/token \\\n --header 'accept: application/json' \\\n --header 'content-type: application/x-www-form-urlencoded' \\\n --data 'username=admin%40admin.com&password=admin&client_id=2&client_secret=SGUVv02b1ppQCgI7ZVeoTZDN6z8SSFLYiMOzzfiE&grant_type=password&scope='\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Response:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "token_type": "Bearer",\n "expires_in": 86400,\n "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz...",\n "refresh_token": "TPSPA1S6H8Wydjkjl+xt+hPGWTagL..."\n}\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"4",children:["\n",(0,s.jsxs)(n.li,{children:["Your Client App should save the Tokens and start requesting secure data, by sending the Access Token in the HTTP\nHeader ",(0,s.jsx)(n.code,{children:"Authorization = Bearer {Access-Token}"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["More info at ",(0,s.jsx)(n.a,{href:"https://laravel.com/docs/passport#password-grant-tokens",children:"Laravel Passport Here"})]}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"WARNING: the Client ID and Secret should not be stored in JavaScript or browser cache, or made accessible in any way."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"So in case of Web Apps (JavaScript) you need to hide your client credentials behind a proxy. Apiato by default\nprovides you with a Web Login Proxy to use for all your trusted first party clients. We'll see below how you can use them."}),"\n",(0,s.jsx)(n.h3,{id:"login-with-proxy-for-first-party-clients",children:"Login with Proxy for first-party clients"}),"\n",(0,s.jsx)(n.p,{children:"Concept: create an endpoint for each trusted client, to be used for a login."}),"\n",(0,s.jsxs)(n.p,{children:["Apiato by default has one url ready for your Web client ",(0,s.jsx)(n.code,{children:"clients/web/login"}),". You can add more as you\nneed for each of your trusted first party clients Apps (example: ",(0,s.jsx)(n.code,{children:"clients/web/users/login"}),", ",(0,s.jsx)(n.code,{children:"clients/mobile/users/login"}),")."]}),"\n",(0,s.jsxs)(n.p,{children:["Behind the scene, that endpoint is appending the corresponding client ID and Secret to your request and making another\ncall to your Auth server with all the required data. ",(0,s.jsx)(n.em,{children:"(this way the client does not need to send the ID and Secret with\nthe request, and he is using his own URL which gives even more control to which client is accessing your Server)"}),". Then\nit returns the Auth response back to the client with the Tokens in it."]}),"\n",(0,s.jsxs)(n.p,{children:["Note: You have to manually extract the Client credentials from the DB and put them in the ",(0,s.jsx)(n.code,{children:".env"}),", for each client."]}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"passport:install"})," it automatically creates one client for you so you can use that for your\nfirst app. Or you can use ",(0,s.jsx)(n.code,{children:"php artisan passport:client --password"})," to generate them."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:".env"})," Example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"CLIENT_WEB_ID=101\nCLIENT_WEB_SECRET=VkjYCUk5DUexJTE9yFAakytWCOqbShLgu9Ql67TI\n"})}),"\n",(0,s.jsx)(n.h3,{id:"login-without-proxy-for-first-party-clients",children:"Login without Proxy for first-party clients"}),"\n",(0,s.jsxs)(n.p,{children:["Login from your App by sending a POST request to ",(0,s.jsx)(n.code,{children:"http://api.apiato.test/v1/oauth/token"})," with ",(0,s.jsx)(n.code,{children:"grant_type=password"}),",\nthe User credentials (",(0,s.jsx)(n.code,{children:"username"})," & ",(0,s.jsx)(n.code,{children:"password"}),"), Client Credentials (",(0,s.jsx)(n.code,{children:"client_id"})," & ",(0,s.jsx)(n.code,{children:"client_secret"}),") and finally the\n",(0,s.jsx)(n.code,{children:"scope"})," which could be empty."]}),"\n",(0,s.jsx)(n.h2,{id:"third-party-clients",children:"B: For third-party clients"}),"\n",(0,s.jsx)(n.p,{children:"Third party clients (User's custom external Apps, who wants to integrate with your Software) always consumes your\npublic API (External API) only."}),"\n",(0,s.jsxs)(n.p,{children:["For third-party clients you need to use the ",(0,s.jsx)(n.strong,{children:"Client credentials grant"})," (A.K.A. Personal Access Tokens). ",(0,s.jsx)(n.em,{children:"This grant\ntype is the simplest and is suitable for machine-to-machine authentication."})]}),"\n",(0,s.jsx)(n.p,{children:"With this grant type your server needs to authenticate the Client App only, before issuing an access token."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"How it works"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["User logs in to your Clients App Interface (an external App made for your users only), go to settings, create Client\n(of type ",(0,s.jsx)(n.code,{children:"personal"}),") and copy the ID and Secret. ",(0,s.jsx)(n.em,{children:"(Note this can be done via an API if you prefer)"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["You may generate a personal client for testing purposes using ",(0,s.jsx)(n.code,{children:"php artisan passport:client --personal"}),"."]}),"\n",(0,s.jsxs)(n.ol,{start:"2",children:["\n",(0,s.jsxs)(n.li,{children:['User add the Client credentials to his "Server Side software" and send a ',(0,s.jsx)(n.strong,{children:"Post"})," request to\n",(0,s.jsx)(n.code,{children:"http://api.apiato.test/v1/oauth/token"})," containing the Client credentials (",(0,s.jsx)(n.code,{children:"client_id"})," and ",(0,s.jsx)(n.code,{children:"client_secret"}),") in\naddition to the ",(0,s.jsx)(n.code,{children:"scope"})," and ",(0,s.jsx)(n.code,{children:"grant_type=client_credentials"}),":"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Request:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"curl --request POST \\\n --url http://api.apiato.test/v1/oauth/token \\\n --header 'accept: application/json' \\\n --header 'content-type: application/x-www-form-urlencoded' \\\n --data 'client_id=1&client_secret=y1RbtnOvh9rpA91zPI2tiVKmFlepNy9dhHkzUKle&grant_type=client_credentials&scope='\n"})}),"\n",(0,s.jsx)(n.p,{children:"Response:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "token_type": "Bearer",\n "expires_in": 86400,\n "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1Ni...",\n "refresh_token": "ZFDPA1S7H8Wydjkjl+xt+hPGWTagX..."\n}\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"3",children:["\n",(0,s.jsxs)(n.li,{children:["The Client will be granted an Access Token to be saved. Then the Client can start requesting secure data, by sending\nthe Access Token in the HTTP Header ",(0,s.jsx)(n.code,{children:"Authorization = Bearer {Access-Token}"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["More info at ",(0,s.jsx)(n.a,{href:"https://laravel.com/docs/passport#personal-access-tokens",children:"Laravel Passport Here"})]}),"\n",(0,s.jsx)(n.h3,{id:"login-without-proxy-for-third-party-clients",children:"Login without Proxy for third-party clients"}),"\n",(0,s.jsx)(n.p,{children:"We usually do not need a proxy for third-party clients as they are most likely making calls form their servers, thus\nthe Client ID and Secret should be secure and not exposed to the users."}),"\n",(0,s.jsxs)(n.p,{children:["Login by sending a POST request to ",(0,s.jsx)(n.code,{children:"http://api.apiato.test/v1/oauth/token"})," with ",(0,s.jsx)(n.code,{children:"grant_type=client_credentials"}),",\nClient Credentials (",(0,s.jsx)(n.code,{children:"client_id"})," & ",(0,s.jsx)(n.code,{children:"client_secret"}),") and finally the ",(0,s.jsx)(n.code,{children:"scope"})," which could be empty."]}),"\n",(0,s.jsxs)(n.p,{children:["Once issued, you can use that Access Token to make requests to protected resources (Endpoints).\nThe Access Token should be sent in the ",(0,s.jsx)(n.code,{children:"Authorization"})," header of type ",(0,s.jsx)(n.code,{children:"Bearer"}),"\n(Example: ",(0,s.jsx)(n.code,{children:"Authorization = Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz..."}),")"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Keep in mind there's no session state when using Tokens for Authentication"})}),"\n",(0,s.jsx)(n.h2,{id:"login-with-custom-attributes",children:"Login With Custom Attributes"}),"\n",(0,s.jsxs)(n.p,{children:["By default, Apiato allow users to log in with their ",(0,s.jsx)(n.code,{children:"email"})," address. However, you may want to also allow users to\nbe able to log in using their ",(0,s.jsx)(n.code,{children:"username"}),"and ",(0,s.jsx)(n.code,{children:"phone"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Here is how to configure and use this feature."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["You may need to adapt your database accordingly (e.g., add the respective field to the ",(0,s.jsx)(n.code,{children:"users"})," table)."]}),"\n",(0,s.jsxs)(n.li,{children:["You may need to adapt the ",(0,s.jsx)(n.code,{children:"Task"})," that ",(0,s.jsx)(n.code,{children:"create"})," a ",(0,s.jsx)(n.code,{children:"User"})," object (e.g., the ",(0,s.jsx)(n.code,{children:"CreateUserByCredentialsTask"}),") accordingly\nto support the new fields. This may also affect your ",(0,s.jsx)(n.code,{children:"Register"})," logic."]}),"\n",(0,s.jsxs)(n.li,{children:["Check the ",(0,s.jsx)(n.code,{children:"App\\Containers\\AppSection\\Authentication\\Configs\\appSection-authentication"})," Configuration file and check the ",(0,s.jsx)(n.code,{children:"login"}),"\nparams in order to configure this feature."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"logout",children:"Logout"}),"\n",(0,s.jsxs)(n.p,{children:["Logout by sending a ",(0,s.jsx)(n.code,{children:"DELETE"})," request to ",(0,s.jsx)(n.code,{children:"http://api.apiato.test/v1/logout/"})," containing the Token in the Header."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "message": "Token revoked successfully."\n}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"responses",children:"Responses"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Authentication failed JSON response:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "message": "An Exception occurred when trying to authenticate the User.",\n "errors": []\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Wrong Client ID or Secret:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "error": "invali
1d_client",\n "error_description": "Client authentication failed",\n "message": "Client authentication failed"\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Access Correct:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "token_type": "Bearer",\n "expires_in": 86400,\n "access_token": "tnJ1eXAiOiJKV1QiLCJhbGciOiJSUzI1Zx...",\n "refresh_token": "ZFDPA1S7H8Wydjkjl+xt+hPGWTagX..."\n}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"change-tokens-expiration-dates",children:"Change Tokens Expiration dates"}),"\n",(0,s.jsxs)(n.p,{children:["Go to ",(0,s.jsx)(n.code,{children:"app/Ship/Configs/apiato.php"})," config file and edit this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-php",children:"/*\n|--------------------------------------------------------------------------\n| Access Token Expiration\n|--------------------------------------------------------------------------\n|\n| In Days. Default to 3650 days = 10 years\n|\n*/\n'expires-in' => env('API_TOKEN_EXPIRES', 3650),\n\n/*\n|--------------------------------------------------------------------------\n| Refresh Token Expiration\n|--------------------------------------------------------------------------\n|\n| In Days. Default to 3650 days = 10 years\n|\n*/\n'refresh-expires-in' => env('API_REFRESH_TOKEN_EXPIRES', 3650),\n"})}),"\n",(0,s.jsxs)(n.p,{children:["To change from days to minutes you need to edit the ",(0,s.jsx)(n.code,{children:"boot"})," function in ",(0,s.jsx)(n.code,{children:"App\\Containers\\AppSection\\Authentication\\Providers\\AuthProvider"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"web-authentication",children:"Web Authentication"}),"\n",(0,s.jsxs)(n.p,{children:["To protect a ",(0,s.jsx)(n.strong,{children:"Web"})," Endpoint from being accessible by unauthenticated users you can use the ",(0,s.jsx)(n.code,{children:"auth:web"})," Middleware."]}),"\n",(0,s.jsx)(n.p,{children:"Example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-php",children:"Route::get('private/page', [Controller::class, 'showPrivatePage'])\n ->middleware('auth:web');\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"If authentication failed, users will be redirected to a login page"})}),"\n",(0,s.jsxs)(n.p,{children:["To change the login page view go to the config file ",(0,s.jsx)(n.code,{children:"app/Containers/AppSection/Authentication/Configs/appSection-authentication.php"}),", and set the name of your login page there as follows:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-php",children:"'login-page-url' => 'login',\n"})}),"\n",(0,s.jsx)(n.p,{children:"This will be looking for (login.html or login.php or login.blade.php)."}),"\n",(0,s.jsx)(n.h2,{id:"refresh-token",children:"Refresh Token"}),"\n",(0,s.jsx)(n.p,{children:"In case your server is issuing a short-lived access tokens, the users will need to refresh their access tokens via the\nrefresh token that was provided to them when the access token was issued."}),"\n",(0,s.jsx)(n.h3,{id:"refresh-token-with-proxy-for-first-party-clients",children:"Refresh Token with proxy for first-party clients"}),"\n",(0,s.jsxs)(n.p,{children:["By default, Apiato provide this endpoint ",(0,s.jsx)(n.code,{children:"http://api.apiato.test/v1/clients/web/refresh"})," for the Web Client to be used\nwhen you need to refresh the token for that client. You can of course create as many\nendpoints as you want for each client. See the code of ",(0,s.jsx)(n.code,{children:"app/Containers/AppSection/Authentication/UI/API/Routes/ProxyRefreshForWebClient.v1.public.php"}),"\nand create similar ones for each client. The most important change will be the ",(0,s.jsx)(n.code,{children:"env('CLIENT_WEB_ID')"})," and\n",(0,s.jsx)(n.code,{children:"env('CLIENT_WEB_SECRET'),"})," passed to the ",(0,s.jsx)(n.code,{children:"ProxyRefreshForWebClientAction"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Those proxy refresh endpoints work in 2 ways. Either by passing the ",(0,s.jsx)(n.code,{children:"refresh_token"})," manually to the endpoint. Or by\npassing it with the HttpCookie. In both cases the code will work, and the server will reply with a response similar to this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "token_type": "Bearer",\n "expires_in": 31500,\n "access_token": "tnJ1eXAiOiJKV1QiLCJhbGciOiJSUzI1Zx...",\n "refresh_token": "ZFDPA1S7H8Wydjkjl+xt+hPGWTagX..."\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:"Containing new Access Token and new Refresh Token."}),"\n",(0,s.jsx)(n.h3,{id:"refresh-token-without-proxy-for-first-party-or-third-party-clients",children:"Refresh Token without proxy for first-party or third-party clients"}),"\n",(0,s.jsxs)(n.p,{children:["The request to ",(0,s.jsx)(n.code,{children:"http://api.apiato.test/v1/oauth/token"})," should contain ",(0,s.jsx)(n.code,{children:"grant_type=refresh_token"}),", the ",(0,s.jsx)(n.code,{children:"client_id"})," &\n",(0,s.jsx)(n.code,{children:"client_secret"}),", in addition to the ",(0,s.jsx)(n.code,{children:"refresh_token"})," and finally the ",(0,s.jsx)(n.code,{children:"scope"})," which could be empty."]}),"\n",(0,s.jsx)(n.h2,{id:"force-email-confirmation",children:"Force Email Confirmation"}),"\n",(0,s.jsxs)(n.p,{children:["By default, a user does not have to confirm his email address to be able to login.\nHowever, to force users to confirm their email (prevent unconfirmed users from accessing the site), you can set\n",(0,s.jsx)(n.code,{children:"'require_email_confirmation' => true,"})," in ",(0,s.jsx)(n.code,{children:"App\\Containers\\AppSection\\Authentication\\Configs\\appSection-authentication.php"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["When email confirmation is enabled (value set to ",(0,s.jsx)(n.code,{children:"true"}),"), the API throws an exception, if the ",(0,s.jsx)(n.code,{children:"User"})," is not yet ",(0,s.jsx)(n.code,{children:"confirmed"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"reset-password",children:"Reset Password"}),"\n",(0,s.jsxs)(n.p,{children:["Use the ",(0,s.jsx)(n.code,{children:"/password-forgot"})," (",(0,s.jsx)(n.code,{children:"app/Containers/AppSection/User/UI/API/Routes/ForgotPassword.v1.public.php"}),")\nand ",(0,s.jsx)(n.code,{children:"/password-reset"})," (",(0,s.jsx)(n.code,{children:"app/Containers/AppSection/User/UI/API/Routes/ResetPassword.v1.public.php"}),") endpoints."]}),"\n",(0,s.jsxs)(n.p,{children:["First you need to send a request to the ",(0,s.jsx)(n.code,{children:"/password-forgot"})," endpoint.\nIt will email you a link and when you make a request to that link it will call the ",(0,s.jsx)(n.code,{children:"/password-reset"})," endpoint."]}),"\n",(0,s.jsxs)(n.p,{children:["Note: For security reason, make sure the reset password URL is set in ",(0,s.jsx)(n.code,{children:"app/Containers/AppSection/User/Configs/appSection-user.php"}),"\nand given to the client App to be sent as parameter when calling the ",(0,s.jsx)(n.code,{children:"/password-forgot"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Note: You must set up the email to get this function to work, however for testing purposes set the ",(0,s.jsx)(n.code,{children:"MAIL_DRIVER=log"})," in\nyour ",(0,s.jsx)(n.code,{children:".env"})," file in order to the see the email content in the log file ",(0,s.jsx)(n.code,{children:"storage/logs/laravel.log"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"social-authentication",children:"Social Authentication"}),"\n",(0,s.jsxs)(n.p,{children:["For Social Authentication visit the ",(0,s.jsx)(n.a,{href:"../additional-features/apiato-containers/social-authentication",children:"Social Authentication"})," page."]})]})}function d(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},28453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>a});var i=t(96540);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.