{
    "componentChunkName": "component---src-templates-article-page-template-js",
    "path": "/how-to/setup-open-id-connect-proxy/",
    "result": {"data":{"markdownRemark":{"frontmatter":{"title":"How to set up OpenID Connect proxy in FTW","slug":"setup-open-id-connect-proxy","updated":"2021-03-02T00:00:00.000Z","category":"how-to-users-and-authentication","ingress":"In this guide, we'll take a look at the process of setting up OpenID Connect (OIDC) proxy to FTW. This allows you to add support for identity providers that Flex doesn't natively support. In this example, we are building the proxy implementation for LinkedIn.","skills":null},"htmlAst":{"type":"root","children":[{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The OpenID Connect (OIDC) support in Flex allows you to integrate login\nsolutions that do not necessarily implement OpenID Connect. The idea is\nto build a suitable login flow in FTW and wrap that login information\ninto an OpenID Connect ID token that can be used to validate user login\nin Flex. With this approach, FTW will serve as an identity provider\ntowards Flex."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Flex verifies the ID token by"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"fetching the JSON Web Key that is hosted by your FTW server, and"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"using that to unsign the token."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"A consequence of this is that the JSON Web Key needs to be publicly\navailable. This means that the proxy setup will not work directly in\nlocalhost. To test out the LinkedIn login, you should e.g.\n"},{"type":"element","tagName":"a","properties":{"href":"/docs/legacy/tutorial/deploy-to-render/"},"children":[{"type":"text","value":"deploy your FTW changes to Render"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In this guide, we'll integrate LinkedIn login to Flex by using FTW as an\nOIDC proxy to Flex. The main steps to take to achieve this are:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a login app in Linkedin"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Configure a new identity provider and client in Flex Console"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Build LinkedIn auth flow in FTW"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Note, that using FTW as an OpenID Connect proxy requires ftw-daily\nversion\n"},{"type":"element","tagName":"a","properties":{"href":"https://github.com/sharetribe/ftw-daily/releases/tag/v7.3.0","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"7.3.0"}]},{"type":"text","value":" or\nftw-hourly version\n"},{"type":"element","tagName":"a","properties":{"href":"https://github.com/sharetribe/ftw-hourly/releases/tag/v9.3.0","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"9.3.0"}]},{"type":"text","value":"."}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"a-note-about-development-environments","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#a-note-about-development-environments","ariaLabel":"a note about development environments permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"A note about development environments"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"For OpenID Connect (OIDC) identity providers, Flex supports RSA signed\nID tokens. RSA is an asymmetric signing function. Therefore, all OIDC\nidentity providers will need to provide their URL (also known as "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"issuer\nlocation"}]},{"type":"text","value":") to Flex so that public signing keys can be fetched for ID\ntoken validation."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"When using FTW as an OIDC proxy, FTW should be served publicly, so that\nFlex can fetch the public signing key used to sign ID tokens used with\nauthentication. This means that when developing OIDC proxy capabilities,\nby default, an FTW application running in "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"localhost"}]},{"type":"text","value":" can not be used as\nan OIDC proxy but the application should be deployed, for example, to a\nstaging environment."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"If you want to develop this functionality complete locally, take a look\nat tools like "},{"type":"element","tagName":"a","properties":{"href":"https://ngrok.com/","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"Ngrok"}]},{"type":"text","value":" or\n"},{"type":"element","tagName":"a","properties":{"href":"https://localtunnel.github.io/www/","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"Localtunnel"}]},{"type":"text","value":" that allow exposing\nyour local ports publicly."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"create-a-login-app-in-linkedin","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#create-a-login-app-in-linkedin","ariaLabel":"create a login app in linkedin permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Create a login app in LinkedIn"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Head to\n"},{"type":"element","tagName":"a","properties":{"href":"https://www.linkedin.com/developers/apps/new","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"LinkedIn apps management page"}]},{"type":"text","value":".\nA LinkedIn account is required."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Click \"Create app\""}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Add app name"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Search the LinkedIn page of your marketplace business. If you do not\nhave a LinkedIn page, you can create one by selecting \"+ Create a new\nLinkedIn Page\"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Fill in the URL to the privacy policy in your marketplace."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Add a logo."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Check the legal agreement and you are ready to click \"Create app\""}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Navigate to the "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"Auth"}]},{"type":"text","value":" tab in your new app view."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Add a new redirect URL:\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<your marketplace URL>/api/auth/linkedin/callback"}]},{"type":"text","value":". So for example,\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"https://www.mymarketplace.com/api/auth/linkedin/callback"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Make a note of the client ID and client secret. You will need these\nvalues later on."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Move to the "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"Products"}]},{"type":"text","value":" tab and add "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"Sign In with LinkedIn"}]},{"type":"text","value":" by\nclicking \"Select\" by the product."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"It takes a few moments for LinkedIn to validate your app for the\n"},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"Sign In"}]},{"type":"text","value":" product."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"configure-a-new-identity-provider-and-client-in-flex-console","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#configure-a-new-identity-provider-and-client-in-flex-console","ariaLabel":"configure a new identity provider and client in flex console permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Configure a new identity provider and client in Flex Console"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"With this proxy implementation, "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"your FTW works as the identity\nprovider towards Flex."}]},{"type":"text","value":" Flex uses your FTW to validate the ID token\nthat wraps the LinkedIn login information. To enable logins in Flex\nusing the OIDC proxy, a corresponding identity provider and identity\nprovider client need to be configured for your marketplace in Flex\nConsole. See the\n"},{"type":"element","tagName":"a","properties":{"href":"/docs/legacy/how-to/enable-open-id-connect-login/"},"children":[{"type":"text","value":"OpenID Connect how-to guide"}]},{"type":"text","value":" for\ninformation on how to add a new identity provider for your marketplace."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Here's some guidance for configuring your FTW as a new identity provider\nand a client to be used as a proxy for LinkedIn."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"identity-provider-name-and-id","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#identity-provider-name-and-id","ariaLabel":"identity provider name and id permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Identity provider name and ID"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The identity provider ID is generated based on the name of the IdP. The\nID will be passed to the Flex API when creating a user or logging in\nusing the proxy. When a user logs in with an identity provider, their\nidentity provider profile is linked to their user account and this\nrelationship is exposed in the\n"},{"type":"element","tagName":"a","properties":{"href":"https://www.sharetribe.com/api-reference/marketplace.html#currentuser-identity-provider","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"currentUser resource"}]},{"type":"text","value":"\nin the Flex API."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"If the intention is to use the FTW to proxy login to multiple services,\nit's advised to create a distinct identity provider for each, and name\nthem so that the ID indicates what is the actual service providing the\nauthentication. In LinkedIn's case the IdP name could be \"FTW LinkedIn\"\nor \"FTW LinkedIn Proxy\"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"identity-provider-url","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#identity-provider-url","ariaLabel":"identity provider url permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Identity provider URL"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Based on this URL, Flex determines the path to an OpenID Connect\ndiscovery document ("},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"[identity provider\nURL]/.well-known/openid-configuration"}]},{"type":"text","value":") and from there on to an ID token\nsigning key."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In Open ID Connect terms, this is the issuer URL. In this setup, your\nFTW acts as the issuer towards Flex, so the URL should point to your\nFTW."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"By default, the identity provider URL should be the root address of your\nFTW application, for example, "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://example.com","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"https://example.com"}]}]},{"type":"text","value":" or, for default\nRender URLs, "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://EXAMPLE.onrender.com","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"https://EXAMPLE.onrender.com"}]}]},{"type":"text","value":". Note, that this URL needs\nto be publicly hosted so a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"localhost"}]},{"type":"text","value":" URL will not work."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"client-id","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#client-id","ariaLabel":"client id permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Client ID"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"When using FTW as on OpenID Connect proxy, you are in charge of\ngenerating a client ID. The value can be any randomly generated string."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"build-linkedin-auth-flow-in-ftw","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#build-linkedin-auth-flow-in-ftw","ariaLabel":"build linkedin auth flow in ftw permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Build LinkedIn auth flow in FTW"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"ftw-as-an-openid-connect-identity-provider","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#ftw-as-an-openid-connect-identity-provider","ariaLabel":"ftw as an openid connect identity provider permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"FTW as an OpenID Connect identity provider"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The FTW templates provide a few helper functions which you can use as a\nstarting point in your customization. When following this guide you will\nnot need to pay too much attention to them as the crucial code is\nprovided for you in the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"linkedin.js"}]},{"type":"text","value":" file below but it's good to be\naware of them. You can find these functions in the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"api-util/idToken.js"}]},{"type":"text","value":"\nfile in your server:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"shell"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-shell"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-shell"]},"children":[{"type":"text","value":"└── server\n    └── api-util\n          └── idToken.js\n          "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":".."}]},{"type":"text","value":"."}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"createIdToken"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Turns information fetched from a 3rd party identity provider (e.g.\nLinkedIn) info a signed JSON Web Token (JWT)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"This function expects three parameters: "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"idpClientId"}]},{"type":"text","value":", "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"user"}]},{"type":"text","value":" and\n"},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"options"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"idpClientId"}]},{"type":"text","value":" is the client id of your custom identity provider you\nhave set up in Console:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"user"}]},{"type":"text","value":" object should contain at least "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"firstName"}]},{"type":"text","value":", "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"lastName"}]},{"type":"text","value":", "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"email"}]},{"type":"text","value":"\nand "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"emailVerified"}]},{"type":"text","value":" fields."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"options"}]},{"type":"text","value":" object contains information about how the id token should be\nsigned and the keys required for that. Currently, Flex supports only\nRS256 signing algorithm so the "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"options"}]},{"type":"text","value":" object should look like this:"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"{ signingAlg: 'RS256', rsaPrivateKey, keyId }"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"openIdConfiguration"}]}]},{"type":"text","value":" and "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"jwksUri"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"These functions can be used to serve an OpenID Connect discovery\ndocument and JSON Web Keys that are used by Flex to validate the ID\ntoken written by your proxy implementation. FTW will automatically use\nthese functions to expose correct endpoints when JWT signing keys are\nconfigured."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"generate-an-rsa-key-pair","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#generate-an-rsa-key-pair","ariaLabel":"generate an rsa key pair permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Generate an RSA key pair"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"A RSA public and private key pair is used to sign and validate an ID\ntoken that is passed from FTW to Flex during the login/signup flow. When\na user successfully logs into LinkedIn, FTW wraps the user information\nto an ID token that is signed with a private key. The corresponding\npublic key is served by FTW in "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"/.well-known/jwks.json"}]},{"type":"text","value":" and it is\nfetched by Flex when an ID token is validated."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In order for the FTW to operate as an OpenID Connect identity provider,\nyou will need to generate a RSA key pair. Both keys need to be in PEM\nformat."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The keys can be generated with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"ssh-keygen"}]},{"type":"text","value":" command line tool by running\nthe following commands. The first one will generate a key pair, with the\nprivate key in PEM format and the public key in SSH public key format.\nThe second command will create a public key in PEM format based on the\npublic key file from the first command."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"# create an RSA key pair, you can leave out the passphrase when prompted\nssh-keygen -f ftw_rsa -t rsa -m PEM\n\n# now you have two files\n# ftw_rsa: private key in PEM format\n# ftw_rsa.pub: public key in SSH public key format\n\n# convert the public key from previous command to PEM format\nssh-keygen -f ftw_rsa.pub -e -m PEM > ftw_rsa_pub"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Now you have two files: "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"ftw_rsa"}]},{"type":"text","value":" and "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"ftw_rsa_pub"}]},{"type":"text","value":" (also you have\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"ftw_rsa.pub"}]},{"type":"text","value":" but that one you don't need). The content of the files\nshould look like the following:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"# ftw_rsa\n\n-----BEGIN RSA PRIVATE KEY-----\nprivate key\nvalue\nhere\n-----END RSA PRIVATE KEY-----\n\n\n# ftw_rsa_pub\n\n-----BEGIN RSA PUBLIC KEY-----\npublic key\nvalue\nhere\n-----END RSA PUBLIC KEY-----"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We will use these key values to configure your application in the next\nsection."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"configure-ftw","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#configure-ftw","ariaLabel":"configure ftw permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Configure FTW"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Add the following environment variables:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"REACT_APP_LINKEDIN_CLIENT_ID"}]},{"type":"text","value":" and "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"LINKEDIN_CLIENT_SECRET"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Set these as the client ID and client secret of your LinkedIn app."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"RSA_PRIVATE_KEY"}]},{"type":"text","value":" and "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"RSA_PUBLIC_KEY"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The RSA key pair we created in the previous section"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The keys are multi-line strings but Heroku is fine with that so you can\npaste the keys in config vars as they are."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"blockquote","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"If you are using Render or some other environment that requires you to\ndeclare environment variables through a file, wrap the RSA keys with\nquotation marks "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"\""}]},{"type":"text","value":" and escape line breaks with the newline character\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"\\n"}]},{"type":"text","value":". Make sure that the RSA key is defined on a single line."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"LINKEDIN_PROXY_IDP_ID"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The identifier of your identity provider that you configure to Flex. It\ndeclares that you are using your FTW OpenID Connect proxy as an identity\nprovider. Use the \"IdP ID\" value of an identity provider client in\nConsole for this variable."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"LINKEDIN_PROXY_CLIENT_ID"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The client ID of your identity provider client that you configure to\nFlex. Use the \"Client ID\" value of an identity provider client in\nConsole for this variable."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"KEY_ID"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The value will be used as the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"kid"}]},{"type":"text","value":" header in ID tokens that are passed\nto Flex when a user logs in with LinkedIn. It is also used as the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"kid"}]},{"type":"text","value":"\nattribute of the JSON Web key that the proxy serves in an endpoint. Even\nthough using a "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"kid"}]},{"type":"text","value":" value in your keys is not compulsory, we heavily\nrecommend using it with your token and the JWK. For example, key caching\nin the Flex API relies heavily on it."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"add-passport-module-dependency","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#add-passport-module-dependency","ariaLabel":"add passport module dependency permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Add Passport module dependency"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We are using "},{"type":"element","tagName":"a","properties":{"href":"http://www.passportjs.org","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"Passport.js"}]},{"type":"text","value":" library for\nhandling the authentication with different identity providers like with\nFacebook and Google. The library offers multiple authentication\nstrategies and there's also a strategy for Linkedin which we are going\nto use in this example."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Add the following entry to the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"dependencies"}]},{"type":"text","value":" map in "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"package.json"}]},{"type":"text","value":" and\nrun "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"yarn install"}]},{"type":"text","value":":"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","string-property","property"]},"children":[{"type":"text","value":"\"passport-linkedin-oauth2\""}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"\"^2.0.0\""}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"implement-the-linkedin-login-flow-in-ftw-backend","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#implement-the-linkedin-login-flow-in-ftw-backend","ariaLabel":"implement the linkedin login flow in ftw backend permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Implement the LinkedIn login flow in FTW backend"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Next, let's add a new file to FTW that handles authentication to\nLinkedIn. You can find the complete file here:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"/docs/legacy/tutorial-assets/linkedin.js"},"children":[{"type":"text","value":"linkedin.js"}]}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Place the file in "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"server/api/auth"}]},{"type":"text","value":" folder inside FTW:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"shell"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-shell"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-shell"]},"children":[{"type":"text","value":"└── server\n    └── api\n        └── auth\n            └── linkedin.js"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The biggest difference between LinkedIn login and e.g. Facebook login\nwhich has first-class support in Flex is that we need to use\n"},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"createIdToken"}]},{"type":"text","value":" helper function to create the id token from the\ninformation we fetched from LinkedIn. This new id token is then passed\nforward to Flex as "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"idpToken"}]},{"type":"text","value":" parameter."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"text","value":"  "},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"createIdToken"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"idpClientId"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":" user"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"signingAlg"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'RS256'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":" rsaPrivateKey"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":" keyId "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"then"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","parameter"]},"children":[{"type":"text","value":"idpToken"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"=>"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" userData "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n        email"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n        firstName"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n        lastName"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n        idpToken"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n        from"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n        defaultReturn"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n        defaultConfirm"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"done"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"null"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":" userData"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"catch"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","parameter"]},"children":[{"type":"text","value":"e"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"=>"}]},{"type":"text","value":" console"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"error"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"e"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Now we'll need to expose login endpoints that invoke functions provided\nby the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"linkedin.js"}]},{"type":"text","value":" file."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"server/apiRouter.js"}]},{"type":"text","value":", add the following import:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n  authenticateLinkedin"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n  authenticateLinkedinCallback"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"require"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'./api/auth/linkedin'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"And after all the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"router.*"}]},{"type":"text","value":" invocations, add LinkedIn login routes:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","comment"]},"children":[{"type":"text","value":"// This endpoint is called when the user wants to initiate authentication with Linkedin"}]},{"type":"text","value":"\nrouter"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"get"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'/auth/linkedin'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":" authenticateLinkedin"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n\n"},{"type":"element","tagName":"span","properties":{"className":["token","comment"]},"children":[{"type":"text","value":"// This is the route for callback URL the user is redirected after authenticating"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","comment"]},"children":[{"type":"text","value":"// with Linkedin. In this route a Passport.js custom callback is used for calling"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","comment"]},"children":[{"type":"text","value":"// loginWithIdp endpoint in Flex API to authenticate user to Flex"}]},{"type":"text","value":"\nrouter"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"get"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'/auth/linkedin/callback'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":" authenticateLinkedinCallback"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Finally, on the server side we need to update\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"server/api/auth/createUserWithIdp.js"}]},{"type":"text","value":" so that a correct IdP client ID\nis passed to the Flex API. In the beginning of the file resolve the\nfollowing environment variables:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"LINKEDIN_PROXY_CLIENT_ID"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" process"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"env"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"LINKEDIN_PROXY_CLIENT_ID"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"LINKEDIN_PROXY_IDP_ID"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" process"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"env"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"LINKEDIN_PROXY_IDP_ID"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"And update the logic that resolves the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"idpClientId"}]},{"type":"text","value":" variable:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" idpClientId "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":"\n  idpId "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"==="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"FACEBOOK_IDP_ID"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"?"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"FACBOOK_APP_ID"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" idpId "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"==="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"GOOGLE_IDP_ID"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"?"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"GOOGLE_CLIENT_ID"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" idpId "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"==="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"LINKEDIN_PROXY_IDP_ID"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"?"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","constant"]},"children":[{"type":"text","value":"LINKEDIN_PROXY_CLIENT_ID"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"null"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"add-a-linkedin-login-button-to-ftw","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#add-a-linkedin-login-button-to-ftw","ariaLabel":"add a linkedin login button to ftw permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Add a LinkedIn login button to FTW"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Once we have added the authentication endpoints to the FTW server, we\nneed to add a button for LinkedIn login to the AuthenticationPage."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"shell"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-shell"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-shell"]},"children":[{"type":"text","value":"└── src\n    └── containers\n        └── AuthenticationPage"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We can once more use the existing Google and Facebook login code as an\nexample an create a similar "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"authWithLinkedin"}]},{"type":"text","value":" function, which adds the\ndefault URL parameters to the API call and then redirects user to the\nauthentication endpoint."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","function-variable","function"]},"children":[{"type":"text","value":"authWithLinkedin"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"=>"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" defaultRoutes "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"getDefaultRoutes"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n    baseUrl"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n    fromParam"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n    defaultReturnParam"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n    defaultConfirmParam"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" defaultRoutes"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n  window"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"location"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"href "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","template-string"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","template-punctuation","string"]},"children":[{"type":"text","value":"`"}]},{"type":"element","tagName":"span","properties":{"className":["token","interpolation"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","interpolation-punctuation","punctuation"]},"children":[{"type":"text","value":"${"}]},{"type":"text","value":"baseUrl"},{"type":"element","tagName":"span","properties":{"className":["token","interpolation-punctuation","punctuation"]},"children":[{"type":"text","value":"}"}]}]},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"/api/auth/linkedin?"}]},{"type":"element","tagName":"span","properties":{"className":["token","interpolation"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","interpolation-punctuation","punctuation"]},"children":[{"type":"text","value":"${"}]},{"type":"text","value":"fromParam"},{"type":"element","tagName":"span","properties":{"className":["token","interpolation-punctuation","punctuation"]},"children":[{"type":"text","value":"}"}]}]},{"type":"element","tagName":"span","properties":{"className":["token","interpolation"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","interpolation-punctuation","punctuation"]},"children":[{"type":"text","value":"${"}]},{"type":"text","value":"defaultReturnParam"},{"type":"element","tagName":"span","properties":{"className":["token","interpolation-punctuation","punctuation"]},"children":[{"type":"text","value":"}"}]}]},{"type":"element","tagName":"span","properties":{"className":["token","interpolation"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","interpolation-punctuation","punctuation"]},"children":[{"type":"text","value":"${"}]},{"type":"text","value":"defaultConfirmParam"},{"type":"element","tagName":"span","properties":{"className":["token","interpolation-punctuation","punctuation"]},"children":[{"type":"text","value":"}"}]}]},{"type":"element","tagName":"span","properties":{"className":["token","template-punctuation","string"]},"children":[{"type":"text","value":"`"}]}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Then we can use the "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"SocialLoginButton"}]},{"type":"text","value":" component to show the option to\nlog in with LinkedIn to the users. Remember to add the LinkedIn related\nmicrocopy keys as well as LinkedIn logo too! Usually, different identity\nproviders have brand centers where you can find the logos and guidelines\nhow to use them. You can download LinkedIn logo from\n"},{"type":"element","tagName":"a","properties":{"href":"https://brand.linkedin.com/downloads","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"LinkedIn brand center"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" linkedinButtonText "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" isLogin "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"?"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"text","value":"FormattedMessage id"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"\"AuthenticationPage.loginWithLinkedIn\""}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"/"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"text","value":"FormattedMessage id"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"\"AuthenticationPage.signupWithLinkedIn\""}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"/"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"text","value":"div className"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"css"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"socialButtonWrapper"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"text","value":"SocialLoginButton onClick"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"=>"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"authWithLinkedin"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"text","value":"span className"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"css"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"buttonIcon"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"LinkedinLogo"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"/"}]},{"type":"text","value":"span"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"linkedinButtonText"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"/"}]},{"type":"text","value":"SocialLoginButton"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"/"}]},{"type":"text","value":"div"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"AuthenticationPage"}]},{"type":"text","value":" component, the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"idp"}]},{"type":"text","value":" const defines what is\npresented as the name of the identity provider in the sign up confirm\npage. By default, it uses the IdP ID stored in a cookie with a\ncapitalized first letter. In case that is not sufficient approach given\nthe IdP ID in use, a custom name for the identity provider can be used\nby, for example, by comparing the IdP ID in the cookie to the one used\nby your proxy IdP and overriding the default when suitable."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"That's it! In order to integrate some other identity provider, implement\ntheir authentication flow using Passport.js or some other method and use\nthe utility functions in "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"api-util/idToken.js"}]},{"type":"text","value":" accordingly to wrap the\nlogin information into an OpenID Connect ID token that can be used to\nlog in to a Flex marketplace."}]}],"data":{"quirksMode":false}},"headings":[{"value":"A note about development environments","depth":2},{"value":"Create a login app in LinkedIn","depth":2},{"value":"Configure a new identity provider and client in Flex Console","depth":2},{"value":"Identity provider name and ID","depth":3},{"value":"Identity provider URL","depth":3},{"value":"Client ID","depth":3},{"value":"Build LinkedIn auth flow in FTW","depth":2},{"value":"FTW as an OpenID Connect identity provider","depth":3},{"value":"Generate an RSA key pair","depth":3},{"value":"Configure FTW","depth":3},{"value":"Add Passport module dependency","depth":3},{"value":"Implement the LinkedIn login flow in FTW backend","depth":3},{"value":"Add a LinkedIn login button to FTW","depth":3}]}},"pageContext":{"slug":"setup-open-id-connect-proxy","category":"how-to-users-and-authentication"}},
    "staticQueryHashes": ["3794076007","439097193","717698143"]}