locked
Cannot obtain refresh_token from https://login.microsoftonline.com RRS feed

  • Question

  • Hi,

    I have a MVC application using Azure Authentication. The application invokes an Azure Function (protected with active directory).

    The function is invoked successfully using bearer token.  The problem occurs inside the azure function. The azure function obtains an Access token from the tenant so graph api can be invoked to return the groups assigned to the user.  The following code is used to obtain the token

     var _resp = request('POST',https://login.microsoftonline.com/'+TENANT_ID+'/oauth2/v2.0/token';,{
      headers:{
            'Content-Type': 'application/x-www-form-urlencoded',
      },
        body: "scope=Directory.Read.All%20Group.Read.All&"+
       "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&"+
       "client_id="+APP_CLIENT_ID+"&"+  
        "client_secret="+APP_CLIENT_SECRET+"&"+ 
       "assertion="+req.headers['x-ms-token-aad-id-token']+"&"+          
       "requested_token_use=on_behalf_of"   
        });

    The Access token obtained is only valid for 1 hour, and only works if I Access the azure function directly from browser the first time. After the first login is done via browser, the MVC application can invoke the function without issues, until the token expires, then the following message is displayed:

    "invalid_grant","error_description":"AADSTS500133: Assertion is not within its valid time range.

    I have read that the problem is because the Access token expired, and a new token must be obtained using the refresh token,

    The problem is that I cannot get a refresh token when invoking https://login.microsoftonline.com/'+TENANT_ID+'/oauth2/v2.0/token

    only Access_token is returned

    Is there any way to overcome this issue?


    Alvaro

    Wednesday, February 27, 2019 10:39 PM

All replies

  • Seems like you are not passing refresh token to the request body. You can Get Refresh token from [X-MS-TOKEN-AAD-REFRESH-TOKEN] header and pass it to the request as "refresh_token"= [X-MS-TOKEN-AAD-REFRESH-TOKEN]

    Your code will look like as shown below:

    var _resp = request('POST',https://login.microsoftonline.com/'+TENANT_ID+'/oauth2/v2.0/token';,{
      headers:{
            'Content-Type': 'application/x-www-form-urlencoded',
      },
        body: "scope=Directory.Read.All%20Group.Read.All&"+
       "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&"+
       "client_id="+APP_CLIENT_ID+"&"+  
        "client_secret="+APP_CLIENT_SECRET+"&"+ 
       "assertion="+req.headers['x-ms-token-aad-id-token']+"&"+           
       "requested_token_use=on_behalf_of"+"&"+"refresh_token"= 
       req.headers[`x-ms-token-aad-refresh-token`]
        });

    Refer the below document for more details around this:

    https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-on-behalf-of-flow#service-to-service-access-token-request

    https://docs.microsoft.com/en-us/azure/app-service/app-service-authentication-how-to#retrieve-tokens-in-app-code
    Thursday, February 28, 2019 9:59 AM
  • There's no header for Refresh token, only for aad-id-token. These are the headers received in the azure function request


       authorization:"Bearer eyJ0eXAiOiJKV1XXXXXXXXXXXXXXXXX",
       connection:"Keep-Alive",
       host:"texxxxxxxxxunction.azurewebsites.net",
       "max-forwards":"9",
       "x-ms-request-root-id":"d0XXXXXX-4e6e5757ab4e27be",
       "x-ms-request-id":"|d0XXXXXX-4e6e5757ab4e27be.2.",
       "request-id":"|d0XXXXX-4e6e5757ab4e27be.2.",
       "x-waws-unencoded-url":"/api/HttpTrigger1?code=LQf6sWsC0Q1f7CXXXXXXXX",
       "client-ip":"100.32.8.73:63918",
       "x-arr-log-id":"1eXXXXX-bdef-4942-a392-f26410fa95f1",
       "disguised-host":"teXXXXXX.azurewebsites.net",
       "x-site-deployment-id":"teXXXXX",
       "was-default-hostname":"teXXXXX.azurewebsites.net",
       "x-original-url":"/api/HttpTrigger1?code=LQfXXXXX",
       "x-forwarded-for":"190.9.2.186:6953",
       "x-arr-ssl":"2048|256|C=US, S=Washington, L=Redmond, O=Microsoft Corporation, OU=Microsoft IT, CN=Microsoft IT TLS CA 4|CN=*.azurewebsites.net",
       "x-forwarded-proto":"https",
       "x-ms-client-principal-name":"XXXX@XXXX.org",
       "x-ms-client-principal-id":"XXXXXXXXXXX-99d7-a26466b1f467",
       "x-ms-client-principal-idp":"aad",
       "x-ms-client-principal":"eyJhdXRoX3R5cCI6ImFhZCIXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
       "x-ms-token-aad-id-token":"eyJ0eXAiOiJKVXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    }

    The MVC application uses Azure AD authentication, but I can get only Access token. Here's a section of the code

    public void Configure(string name, OpenIdConnectOptions options) {
     options.ClientId = _azureOptions.ClientId;
     options.Authority = $ "{_azureOptions.Instance}{_azureOptions.TenantId}/v2.0"; // V2 specific 
     options.UseTokenLifetime = true;
     options.SaveTokens = true;
     options.RequireHttpsMetadata = false;
     options.TokenValidationParameters.ValidateIssuer = false; // accept several tenants               
     options.Events = new OpenIdConnectEvents {


      OnTokenValidated = context => {

       var keys = context.HttpContext.Request.Headers.Keys;

       var ms_aspnetcore_token = context.HttpContext.Request.Headers["MS-ASPNETCORE-TOKEN"];

       // Add the access_token as a claim, as we may actually need it
       var accessToken = context.SecurityToken as JwtSecurityToken;

       if (accessToken != null) {
        ClaimsIdentity identity = context.Principal.Identity as ClaimsIdentity;
        if (identity != null) {
         identity.AddClaim(new Claim("access_token", accessToken.RawData));
        }
       }

       return Task.CompletedTask;
      }
     };
    }

    Maybe I'm missing some parameters?


    Alvaro


    Thursday, February 28, 2019 2:23 PM
  • Thanks for the URL reference. That helped, but still have some issues. After accessing https://resources.azure.com and configuring the authsettings, after adding the additionalLoginParams, I wasn't able to Access the Azure function from browser. I had to add clientSecret value in order to Access the Azure Function (as before)

    The problem now, is that I can Access the Azure function using browser (and now I have the refresh token in the headers inside azure function).  But I cannot invoke the azure function from the MVC application using the bearer token as before.  I added the client secret as configuration option but no luck

    Any hint?


    Alvaro

    Friday, March 1, 2019 3:59 PM
  • Hey Alvaro

    It looks like it's been some time. Were you able to get this issue resolved through different means/methods? If so, would you kindly share the solution with us here so that others visiting this post can learn from it?
    Thursday, April 11, 2019 8:33 PM