Giter Club home page Giter Club logo

ms-identity-javascript-v2's Introduction

Vanilla JavaScript Single-page Application secured with MSAL.js

This sample has been archived and is no longer being maintained. You can find a more recent version of this sample here

For access to the project files, please visit the branch main.

Disclaimer

The sample in this repository is no longer maintained and is kept for historical reasons. The sample in the main branch is not guaranteed to work with the latest versions of the libraries it depends on.

ms-identity-javascript-v2's People

Contributors

darrenjrobinson avatar derisen avatar hamiltonha avatar henrymbuguakiarie avatar microsoft-github-operations[bot] avatar microsoftopensource avatar naihuiw avatar nmenglund avatar oshihirii avatar owenrichards1 avatar pkanher617 avatar salman90 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ms-identity-javascript-v2's Issues

on login -> not getting code back in the response on signIn (getting accessToken back instead)

Please follow the issue template below. Failure to do so will result in a delay in answering your question.

Library

Important: Please fill in your exact version number above, e.g. [email protected].
[email protected]

Framework

Description

Error Message

Security

  • [ no ] Is this issue security related?

Version:

MSAL Configuration

// Provide configuration values here.
// For Azure B2C issues, please include your policies.

Reproduction steps

  • download sample app
  • run npm install
  • fill in variables in authConfig.js
  • go to localhost:3000/index.html
  • log in (can log in totally fine)
  • gets accessToken back instead of auth code which we need to pass to our backend.
// Provide relevant code snippets here.
// For Azure B2C issues, please include your policies.

Expected behavior

Get auth code back in the response but currently only getting authToken back instead.

Browsers/Environment

  • [ x] Chrome
  • Firefox
  • Edge
  • Safari
  • IE
  • Other (Please add browser name here)

"type:cors, status: 200 ok" response from graph endpoint

Please follow the issue template below. Failure to do so will result in a delay in answering your question.

Library

Description

The loginpopup call works fine and I can log in and get a accesstoken that I have tested in postman, and the token works fine as well. My problem is that when I make a call to graph like described in this tutorial I get an cors response from graph.
In the network tab the request is displayed as "200 OK"
image

But the object that is returned is of type "cors"
image

I copied the function from this tutorial.

.....
    fetch(endpoint, options)
      .then((response) => {
        console.log(response);  //This is the response that is "type: cors" from image above
      })
      .then((response) => callback(response, endpoint)) //Here the response is null/undefined
      .catch((error) => console.log(error));
  }

It is a SPA that I have registered in Azure AD like described here: https://docs.microsoft.com/en-us/graph/tutorials/javascript?tutorial-step=2
Maybe I have to do some more configuration to avoid the cors response??

showWelcomeMessage wrong argument ??

username = currentAccounts[0].username;
showWelcomeMessage(username);

function showWelcomeMessage(account) {
// Reconfiguring DOM elements
cardDiv.style.display = 'initial';
welcomeDiv.innerHTML = Welcome ${account.**username**};
signInButton.setAttribute("onclick", "signOut();");
signInButton.setAttribute('class', "btn btn-success")
signInButton.innerHTML = "Sign Out";
}

The reference document link in README.md is Implicit grant flow.

In Readme.md line 55, The link to "For more information, see the documentation" in 1.3 of "Running the sample" is below,
but this is the Quickstart of Implict grant Flow.

https://docs.microsoft.com/azure/active-directory/develop/quickstart-v2-javascript

The following authentication code flow Quickstart also exists, so it is better to change.

https://docs.microsoft.com/azure/active-directory/develop/quickstart-v2-javascript-auth-code

Can I create Pull Requests to fix link?

Issue with AADSTS7000218 - 'client_assertion' or 'client_secret'.

Hello,

I get this error:

ServerError: invalid_client: 7000218 - [2020-09-25 07:40:47Z]: AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.

after removing "Mail.Read" from scope, because I don't need it:

scopes: ["Mail.Read", "openid", "profile", "User.Read"],

what could be the issue here?

Access to fetch from origin has been blocked by CORS

We;re having a bit of a similar issue as described here. Currently when running the sample code with msal version 1, which uses the implicit grant flow, all works fine. However, when we try to use this sample that uses msal 2 it fails with the following error:

image

Updating the Azure App Regisrtation to use the "SPA Redirect URI" did not fix it:
image

We also tried to disable "implicit grant" in the hope that would resolve the CORSS issue but no luck. Is there still something we're missing here?

  "dependencies": {
    "@azure/msal-browser": "^2.0.0-beta.0",
    "express": "^4.17.1",
    "morgan": "^1.10.0",
    "yargs": "^15.3.1"
  },

Path to index.html is wrong and updating it results in javascript errors.

Starting the server with "npm start" and calling the website results in an error (Error: ENOENT: no such file or directory, stat '.../ms-identity-javascript-v2/index.html').
The index.html can't be found, because it's not located in the root directory.

In server.js:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + '/index.html'));
});

should be:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + '/app/index.html'));
});

Doing so brings up the website but results in the following java-script errors:
Uncaught SyntaxError: Unexpected token '<' authConfig.js:1
Uncaught SyntaxError: Unexpected token '<' graphConfig.js:1
Uncaught SyntaxError: Unexpected token '<' ui.js:1
Uncaught SyntaxError: Unexpected token '<' authPopup.js:1
Uncaught SyntaxError: Unexpected token '<' graph.js:1

Configuration script registers a web app; needs to register a SPA

Please follow the issue template below. Failure to do so will result in a delay in answering your question.

Library

Important: Please fill in your exact version number above, e.g. [email protected].

Framework

Description

The sample application ms-identity-javascript-2 works if the app is registered manually but the provided Configuration.ps1 script will cause the app to fail with a CORS error. This is because the script registers a web app and not a Single Page Application.

Error Message

When running the app with the incorrectly configured app registration, this error appears in the browser console:

Access to fetch at 'https://login.microsoftonline.com/common/oauth2/v2.0/token' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Security

  • Is this issue security related?

Regression

  • Did this behavior work before?

Version:

MSAL Configuration

// Provide configuration values here.
// For Azure B2C issues, please include your policies.

Reproduction steps

Use the sample following the instructions in the AppCreationScripts folder, and running the supplied Configure.ps1 script before executing the application. In this case, the application logs the user in but fails to provide an access token. No information is displayed on the web page and the error above appears in the browser console.

Expected behavior

The application should succeed and display information from the Microsoft graph

Browsers/Environment

  • Chrome
  • Firefox
  • Edge
  • Safari
  • IE
  • Other (Please add browser name here)

401 even with a valid token

Hi, MS Identity team,

First, I want to say that I appreciate the work you guys are doing to simplify auth as a whole. It's my weakest point in development, by far. I just feel like there's something I'm not getting and your work is helping. So here's my situation...

I have a .Net Core 3.1 Web API I want to protect with an AAD-issued bearer access token. I'm getting the token using MSAL and that is working fine. I've verified the token at jwt.ms and everything looks good: aud is my API's client ID from AAD, scp is my custom scope that I'm requesting, and iss is login.microsoftonline.com/<my tenant id> as expected. I get the token with MSAL and add it to my request using JavaScript fetch and adding the token to the 'Authentication' header with the value Bearer <token>.

If I leave off the [Authorize] attribute in the web API (allowing anonymous access), I can see that the token is indeed included in the request headers and that the value is the same as it should be. However, when I add the [Authorize] attribute, the response is a 401 and no code is being run in the API.

Details of my configurations are below. Please let me know what other information I can provide to figure this out. If need be, also let me know if there's a better place to ask for this type of help.

CLIENT

msalConfig.js

import * as msal from '@azure/msal-browser'

// Config object to be passed to Msal on creation
export const msalConfig = {
  auth: {
      clientId: "...my client id...",
      authority: "https://login.microsoftonline.com/... my tenant id ...",
      navigateToLoginRequestUrl: false
  },
  cache: {
      cacheLocation: "sessionStorage", // This configures where your cache will be stored
      storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
  },
  system: {
      loggerOptions: {
          loggerCallback: (level, message, containsPii) => {
              if (containsPii) {
                  return;
              }
              switch (level) {
                  case msal.LogLevel.Error:
                      console.error(message);
                      return;
                  case msal.LogLevel.Info:
                      console.info(message);
                      return;
                  case msal.LogLevel.Verbose:
                      console.debug(message);
                      return;
                  case msal.LogLevel.Warning:
                      console.warn(message);
                      return;
              }
          }
      }
  }
};

// Add here scopes for id token to be used at MS Identity Platform endpoints.
export const loginRequest = {
  scopes: ["User.Read"]
};

// Add here the endpoints for MS Graph API services you would like to use.
export const graphConfig = {
  graphMeEndpoint: "https://graph.microsoft-ppe.com/v1.0/me",
  graphMailEndpoint: "https://graph.microsoft-ppe.com/v1.0/me/messages"
};

// Add here scopes for access token to be used at MS Graph API endpoints.
export const tokenRequest = {
  scopes: ["Mail.Read"],
  forceRefresh: false // Set this to "true" to skip a cached token and go to the server to get a new token
};

export const silentRequest = {
  scopes: ["openid", "profile", "User.Read", "Mail.Read"]
};

export const apiRequest = {
  scopes: ["api://...my client id.../Access.Grant"]
}

auth.js

import * as msal from '@azure/msal-browser'

import {
  msalConfig,
  loginRequest
} from './msalConfig'

// Browser check variables
// If you support IE, our recommendation is that you sign-in using Redirect APIs
// If you as a developer are testing using Edge InPrivate mode, please add "isEdge" to the if check
const ua = window.navigator.userAgent;
const msie = ua.indexOf("MSIE ");
const msie11 = ua.indexOf("Trident/");
// const msedge = ua.indexOf("Edge/");
const isIE = msie > 0 || msie11 > 0;
// const isEdge = msedge > 0;

let signInType;
let username = "";

// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication(msalConfig);

// Redirect: once login is successful and redirects with tokens, call Graph API
myMSALObj.handleRedirectPromise().then(handleResponse).catch(err => {
    console.error(err);
});

function handleResponse(resp) {
    if (resp !== null) {
        username = resp.account.username;
        // showWelcomeMessage(resp.account);
    } else {
        // need to call getAccount here?
        const currentAccounts = myMSALObj.getAllAccounts();
        if (!currentAccounts || currentAccounts.length < 1) {
            return;
        } else if (currentAccounts.length > 1) {
            // Add choose account code here
        } else if (currentAccounts.length === 1) {
            username = currentAccounts[0].username;
            // showWelcomeMessage(currentAccounts[0]);
        }
    }
}

export async function getAccounts() {
  let accounts = myMSALObj.getAllAccounts();
  return accounts;
}

export async function signIn(method) {
    signInType = isIE ? "loginRedirect" : method;
    if (signInType === "loginPopup") {
      try {
        let response = await myMSALObj.loginPopup(loginRequest);
        return response;
      }
      catch (err) {
        console.error(err);
      }       
    } else if (signInType === "loginRedirect") {
      return myMSALObj.loginRedirect(loginRequest)
    }
}

export function signOut() {
    const logoutRequest = {
        account: myMSALObj.getAccountByUsername(username)
    };

    myMSALObj.logout(logoutRequest);
}

export async function getTokenPopup(request, account) {
    request.account = account;
    return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
        console.log("silent token acquisition fails.");
        if (error instanceof msal.InteractionRequiredAuthError) {
            console.log("acquiring token using popup");
            return myMSALObj.acquireTokenPopup(request).catch(error => {
                console.error(error);
            });
        } else {
            console.error(error);
        }
    });
}

// This function can be removed if you do not need to support IE
export async function getTokenRedirect(request, account) {
    request.account = account;
    return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
        console.log("silent token acquisition fails.");
        if (error instanceof msal.InteractionRequiredAuthError) {
            // fallback to interaction when silent call fails
            console.log("acquiring token using redirect");
            myMSALObj.acquireTokenRedirect(request);
        } else {
            console.error(error);
        }
    });
}

Vue component (only showing script tag for brevity)

<script>
import * as auth from '../msal';

export default {
  name: 'HelloWorld',
  props: {
    msg: String

  },
  data() {
    return {
      user: {},
      requests: { ...auth.requests },
      holds: []
    }
  },
  methods: {
    async login() {
      let response = await auth.signIn('loginPopup');
      this.user = {...response.account};
    },
    async getApiToken() {
      let response = await auth.getTokenPopup(this.requests.api, this.user);
      console.log(response);
      return response;
    },
    async getData() {
      let tokenResponse = await this.getApiToken();
      let response = await fetch('https://localhost:4001/api/data', { headers: new Headers ({ "Authentication": `Bearer ${tokenResponse.accessToken}`})});
      if (response.status == 401) {
        // eslint-disable-next-line no-debugger
        debugger
        console.log('nope')
      } else {
        let data = await response.json();
        this.holds = data;
      }
    }
  },
  computed: {
    auth() {
      return auth;
    }
  }
}
</script>

API

Startup.cs (only showing relevant parts)

public void ConfigureServices (IServiceCollection services)
        {
            services.AddMicrosoftWebApiAuthentication(Configuration);

            services.AddCors();
            services.AddControllers();
            services.AddHttpContextAccessor();
            services.AddDbContext<ConfigContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("Config")));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure (IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseHttpsRedirection(); 
            app.UseCors(o => o.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();            
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {                
                endpoints.MapControllers();
            });
        }

appSettings.json

...
"AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "Domain": "... my domain ... .onmicrosoft.com", 
        "TenantId": "... my AAD tenant id ...", 
        "ClientId": "... my API's AAD client id ..."
    }
...

IE11 ES6 Syntax Error for =>

Please follow the issue template below. Failure to do so will result in a delay in answering your question.

Library

Important: Please fill in your exact version number above, e.g. [email protected].

Framework

Description

The sample doesnt work on IE 11, throws syntax error on ES6 comptatiblity for =>

Error Message

Syntax error

Security

  • Is this issue security related?

Regression

  • Did this behavior work before?

Version:

MSAL Configuration

// Provide configuration values here.
// For Azure B2C issues, please include your policies.

Reproduction steps

// Provide relevant code snippets here.
// For Azure B2C issues, please include your policies.

Expected behavior

Tried babel polyfill , but tht doesnt seem to fix the issue.

Browsers/Environment

  • Chrome
  • Firefox
  • Edge
  • Safari
  • [x ] IE
  • Other (Please add browser name here)

error

Protecting my own Web API?

I went through this sample and was able to access the Graph API.

I have a use case where I would like to protect my own web api by verifying the same Bearer token obtained with this flow.

My web api is using Node.js and I tried using passport-azure-ad middleware with the BearerToken strategy to protect my routes. However the token generated with PKCE flow does not seem to be compatible with the JWT verify logic from passport-azure-ad. I get an error saying the JWT has an invalid signature.

Are there any samples with Node.js where I could protect my own web apis using the Auth token obtained from this PKCE flow?

OauthAllowImplicitFlow set to True. MSAL 2.x apps do not support Implicit flow.

Please follow the issue template below. Failure to do so will result in a delay in answering your question.

Library

Description

Hello, I have a question regarding "Oauth2AllowImplicitFlow" option in script "Configure.ps1"
Why -Oauth2AllowImplicitFlow is set to True? Is this different Implicit parameter?

$spaAadApplication = New-AzureADApplication -DisplayName "ms-identity-javascript-v2" `
                                               -HomePage "http://localhost:3000/" `
                                               -ReplyUrls "http://localhost:3000/" `
                                               -IdentifierUris "https://$tenantName/ms-identity-javascript-v2" `
                                               -AvailableToOtherTenants $True `
                                               -Oauth2AllowImplicitFlow $true `
                                               -PublicClient $False

Reading more MSAL.js 2.x apps do not support Implicit flow. I have tested authentication with and without and it worked in both ways:
image

Looking here it seems enabling Implicit will not support refresh token?

Is the AccessToken supposed to be Version 1?

Please follow the issue template below. Failure to do so will result in a delay in answering your question.

Library

  • [https://alcdn.msauth.net/browser/2.30.0/js/msal-browser.js]

Description

Is the AccessToken supposed to be Version 1? I have followed the setup instructions for the app registration and the nodejs app. I have tried three different app registrations in my tenant and they all are returning an access token with v1 and an id token as v2. I found a comment here that explains to add a property to the manifest. However it is still generating v1 access tokens even after adding it.

AzureAD/microsoft-authentication-library-for-js#3414 (comment)

No authentication after redirect

When using msal 1.3.0 there was no need to use the handleRedirectCallback() method. The same is true for "@azure/msal-browser": "^2.0.0-beta.2" but they handle things differently. In the new version authentication after a redirect does not happen automatically unless the page is refreshed a second time after the user authenticated on the Microsoft sign on page.

I have created a repo with the original code used by msal 1.3.0 in the master branch without issues and the new code used by msal 2 in the test-msal-2 branch that needs an extra refresh after the user is navigated back to the SPA to see that he is authenticated.

When I enable the code for authRedirectCallBack(), which comes with the sample code, it keeps looping and refreshing the page all the time.

Thank you for having a look at what I did wrong or if this is an msal code issue.

Cannot seem to get the configuration to work

I have set authority to https://tenant.b2clogin.com/tenant.onmicrosoft.com/B2C_1A_Samssignup_signin and I receive error 400 - AADSTS50049: Unknown or invalid instance.

I have also tried https://tenant.b2clogin.com/tenant.onmicrosoft.com/tfp/B2C_1A_Samssignup_signin

const msalConfig = {
    auth: {
        clientId: 'theclientid',
        authority: 'https://tenant.b2clogin.com/tenant.onmicrosoft.com/B2C_1A_Samssignup_signin',
        redirectUri: 'http://localhost:3000/',
    },
    cache: {
        cacheLocation: "sessionStorage", // This configures where your cache will be stored
        storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
    }
};

Could anyone advise what's wrong?

TS2322: Type 'string | undefined' is not assignable to type 'string'

In our project we upgraded from msal 1.3.0 to "@azure/msal-browser": "^2.0.0-beta.2". Everything seems to work fine except for the following TypeScript error message:

TS2322: Type 'string | undefined' is not assignable to type 'string'.

This comes from expecting the idTokenClaims.oid to be a string:

const accountID = ref('')

export const setAccountID = () => {
  const account = auth.getAccount()

  if (account) {
    accountID.value = account.idTokenClaims.oid
  } else {
    accountID.value = ''
  }
}

In the old library this was not an issue. Should the property oid not always be populated with a string when getAccount() is successful as it identifies the logged on user?

Our current workaround is this:

const accountID = ref('')

export const setAccountID = () => {
  const account = auth.getAccount()

  if (account) {
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    accountID.value = account.idTokenClaims.oid!
  } else {
    accountID.value = ''
  }
}

Being fairly new to TypeScript and web development in general I was wondering if I did something wrong or if there's a better way to handle this? Full code can be found here.

Not working due to bug in msal-browser.js 2.3.1

Library

Framework

Description

See related issue to the msal library here: AzureAD/microsoft-authentication-library-for-js#2476

Error Message

Security

  • Is this issue security related?

Regression

  • Did this behavior work before?

Version: 2.3.0

MSAL Configuration

// Provide configuration values here.
// For Azure B2C issues, please include your policies.

Reproduction steps

Configure the app
Run the app
Try to log
Page stays the same as the error occurs in console.
Works with msal-browser 2.3.0

Expected behavior

After login, the /token request fails as described in the related issue

The console logs this error:
msal.js:46 [AcquireTokenSilent] Unhandled Error:TypeError TypeError: Cannot read property 'length' of null
at Function.ServerTelemetryManager.maxErrorsToSend (index.es.js:7220)
at ServerTelemetryManager.generateLastRequestHeaderValue (index.es.js:7136)
at RefreshTokenClient.BaseClient.createDefaultTokenRequestHeaders (index.es.js:4286)
at RefreshTokenClient. (index.es.js:6357)
at step (index.es.js:394)
at Object.next (index.es.js:324)
at fulfilled (index.es.js:276)

Browsers/Environment

  • Chrome
  • Firefox
  • Edge
  • Safari
  • IE
  • Other (Please add browser name here)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.