title: Alexa Skill with Azure AD B2C Auth expires after an hour
body: <p>I am currently building an Alexa skill backed by Azure Functions (.NET Core/C#) and Azure AD B2C for authentication.</p>
  
  <p>For the initial setup, I used mostly used the instructions found in <a href="https://devblogs.microsoft.com/premier-developer/amazon-alexa-skills-authenticated-by-azure-active-directory-and-backed-by-an-azure-function/" rel="nofollow noreferrer">this arcticle</a>. Since, the article was written a couple of years ago, I had to make a few changes. In the end, I landed on the following configuration:</p>
  
  <h2>Azure Active Directory B2C</h2>
  
  <p>As I mentioned, we are using AAD B2C for authentication. Users of a related application are able to sign-up and sign-in to a React application. The idea is to provide an alternative interface for said users through Alexa intents + utterances.</p>
  
  <p>I created an application for Alexa in AAD B2C with the following settings:</p>
  
  <h3>Properties</h3>
  
  <ul>
  <li>Web App / Web API: Yes</li>
  <li>Allow implicit flow: Yes</li>
  <li>Reply URLs: I entered the values provided by the Alexa skill setup (e.g. <a href="https://pitangui.amazon.com/api/skil/link/.." rel="nofollow noreferrer">https://pitangui.amazon.com/api/skil/link/..</a>.); there are three different ones. I also added one for my azure function app (this is something that could be incorrect. It was part of what I did while diagnosing other earlier problems); it's in the format: <a href="https://myfuncname.azurewebsites.net/.auth/login/aad/callback" rel="nofollow noreferrer">https://myfuncname.azurewebsites.net/.auth/login/aad/callback</a> (Do I even need this???)</li>
  <li>App ID URI: <a href="https://myorg.onmicrosoft.com/alexa" rel="nofollow noreferrer">https://myorg.onmicrosoft.com/alexa</a></li>
  <li>Include native client: No</li>
  </ul>
  
  <h3>Keys</h3>
  
  <p>I generated a single <em>App Key</em>, which I'm using as the Secret in the <em>Account Linking</em> section in the Alexa Developer Console.</p>
  
  <p><strong>Many of the examples online mention setting an explicit expiration date here of 1 or 2 years; however, I am not presented with any options at all (i.e. no expiration option), just the code. Could this be part of the problem???</strong></p>
  
  <h3>API Access</h3>
  
  <ul>
  <li>In the <em>Published scopes</em> section, the Scope's name is <code>user_impersonation</code>. The description is "Access this app on behalf of the signed-in user". The full scope value is: <a href="https://myorgsname.onmicrosoft.com/alexa/user_impersonation" rel="nofollow noreferrer">https://myorgsname.onmicrosoft.com/alexa/user_impersonation</a>.</li>
  </ul>
  
  <p>For API Access, I have to API entries here:</p>
  
  <ul>
  <li>One that uses the <code>user_impersonation</code> scope mentioned above.</li>
  <li>The second, titled "Access the user's profile", uses:
  
  <ul>
  <li>Acquire an id_token for users (openid)</li>
  <li>Acquire a refresh_token for users (offline_access)</li>
  </ul></li>
  </ul>
  
  <h3>AAD B2C User Flow</h3>
  
  <p>The user flow that I'm using allows signing up and signing in, it utilizes the following configuration:</p>
  
  <p><strong>Properties</strong></p>
  
  <p>Misc</p>
  
  <ul>
  <li>Enable JavaScript enforcing page layout (preview): On</li>
  </ul>
  
  <p>Token lifetime</p>
  
  <ul>
  <li>Access &amp; ID token lifetimes (minutes): 60</li>
  <li>Refresh token lifetime (days): 14</li>
  <li>Refresh token sliding window lifetime: "Bounded".</li>
  <li>Lifetime length (days): 90</li>
  </ul>
  
  <p>Token compatibility settings</p>
  
  <ul>
  <li>Issuer (iss) claim: <code>https://&lt;domain&gt;/&lt;b2c-tenant-guid&gt;</code></li>
  <li>Subject (sub) claim: ObjectID</li>
  <li>Claim representing user flow: tfp</li>
  </ul>
  
  <p>Session behavior</p>
  
  <ul>
  <li>Web app session lifetime (minutes): 1440</li>
  <li>Web app session timeout: Rolling</li>
  <li>Single sign-on configuration: Tenant</li>
  <li>Require ID Token in logout requests: No</li>
  </ul>
  
  <h3>Azure Function Authentication Middleware</h3>
  
  <p>For the authentication layer within the Azure Function, I'm utilizing the method described in <a href="https://devblogs.microsoft.com/premier-developer/amazon-alexa-skills-authenticated-by-azure-active-directory-and-backed-by-an-azure-function/" rel="nofollow noreferrer">the article mentioned above</a>.</p>
  
  <h2>Alexa Developer Console</h2>
  
  <p>On the Alexa side of things, I have a really simple skill setup with the following settings:</p>
  
  <h3>Endpoint</h3>
  
  <p>My endpoint uses the <em>HTTPS</em> option with the default region set to the fully-qualified HTTPS endpoint of my Azure Function App's handler function.</p>
  
  <p>The certificate set to "My development endpoint is a sub-domain of a domain that has a wildcard ..."</p>
  
  <h3>Account Linking</h3>
  
  <p>The account linking settings are as outlined below:</p>
  
  <ul>
  <li>Do you allow uses to create an account or link to ...: Toggled On</li>
  <li>Allow users to enable skill without account linking: Toggled On</li>
  <li>Allow users to link their account to your skill from within your application or website: Toggled Off</li>
  <li>Auth Code Grant: On</li>
  <li>Authorization URI: <code>https://myorg.b2clogin.com/myorg.onmicrosoft.com/oauth2/v2.0/authorize?p=&lt;sign-in-user-flow-policy-name&gt;</code></li>
  <li>Access Token URI: <code>https://myorg.b2clogin.com/myorg.onmicrosoft.com/oauth2/v2.0/token?p=&lt;sign-in-user-flow-policy-name&gt;</code></li>
  <li>Your Client ID: AAD B2C App GUID</li>
  <li>Your Secret: Key generated in App settings in AAD B2C for my Alexa Skill App (mentioned in the AAD B2C setup info above).</li>
  <li>Your Authentication Scheme: HTTP Basic</li>
  <li>Scope: openid <strong>and</strong> <a href="https://myorg.onmicrosoft.com/alexa/user_impersonation" rel="nofollow noreferrer">https://myorg.onmicrosoft.com/alexa/user_impersonation</a></li>
  <li>Domain List: login.microsoftonline.com <strong>and</strong> myorg.b2clogin.com <strong>Note: This is probably wrong as I didn't know what to put here. The article above doesn't mention this setting at all</strong></li>
  <li>Default Access Token Expiration Time: 3600</li>
  </ul>
  
  <p>Note: The Alexa Redirect URLS at the bottom are what I put in AAD B2C for the <em>Reply URL</em> section.</p>
  
  <h2>The Problem</h2>
  
  <p>Now for the most important part, <strong>The Problem</strong>. Everything seems to work at first...I'm able to go to alexa.amazon.com and utilize <em>Link Account</em> (which redirects me to and from my AAD B2C-driven login screen). Once I link accounts, I'm able to successfully utilize an utterance and receive a reply.</p>
  
  <p>The problems starts when I wait an hour (I believe it's an hour). Attempting to initiate the Intent after an hour yields an error on the Azure Function app side of things when it tries to validate the Auth Token.</p>
  
  <p>Can anyone provide me some guidance as to what I may have setup incorrectly or at least some things that I should look into? As I mentioned at the start of this question, many of the references that I'm finding online are out-of-date and do not cover all of the settings that I'm expected to utilize. Many of them are still using microsoftonline.com authority vs. b2clogin.com.</p>
  
  <p><strong>At a glance, I would assume that the problem is that the Alexa skill is failing to refresh its token after it expires after an hour. What do I need to do to ensure that it refreshes correctly?</strong></p>