diff --git a/samples/msal-core-samples/VanillaJSTestApp/app/adfs/Readme.md b/samples/msal-core-samples/VanillaJSTestApp/app/adfs/Readme.md
new file mode 100644
index 0000000000..9dc9056f60
--- /dev/null
+++ b/samples/msal-core-samples/VanillaJSTestApp/app/adfs/Readme.md
@@ -0,0 +1,7 @@
+# ADFS Support
+
+MSAL.js supports connecting to Azure AD, which signs in managed-users (users managed in Azure AD) or federated users (users managed by another identity provider such as ADFS). MSAL.js does not differentiate between these two types of users. As far as it’s concerned, it talks to Azure AD. The authority that you would pass in this case is the normal Azure AD Authority: `https://login.microsoftonline.com/{Enter_the_Tenant_Info_Here}`
+
+MSAL.js also supports directly connecting to ADFS 2019, which is OpenID Connect compliant and has support for scopes and PKCE. This support requires that a service pack [KB 4490481](https://support.microsoft.com/en-us/help/4490481/windows-10-update-kb4490481) is applied to Windows Server. When connecting directly to ADFS, the authority you'll want to use to build your application will be of form `https://mysite.contoso.com/adfs/`
+
+Currently, there are no plans to support a direct connection to ADFS 16 or ADFS v2. ADFS 16 does not support scopes, and ADFS v2 is not OIDC compliant.
diff --git a/samples/msal-core-samples/VanillaJSTestApp/app/adfs/auth.js b/samples/msal-core-samples/VanillaJSTestApp/app/adfs/auth.js
new file mode 100644
index 0000000000..13d6323c85
--- /dev/null
+++ b/samples/msal-core-samples/VanillaJSTestApp/app/adfs/auth.js
@@ -0,0 +1,93 @@
+// 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;
+
+// Create the main myMSALObj instance
+// configuration parameters are located at authConfig.js
+const myMSALObj = new Msal.UserAgentApplication(msalConfig);
+
+// Register Callbacks for Redirect flow
+myMSALObj.handleRedirectCallback(authRedirectCallBack);
+
+function authRedirectCallBack(error, response) {
+ if (error) {
+ console.log(error);
+ } else {
+ if (response.tokenType === "id_token" && myMSALObj.getAccount() && !myMSALObj.isCallback(window.location.hash)) {
+ console.log('id_token acquired at: ' + new Date().toString());
+ showWelcomeMessage(myMSALObj.getAccount());
+ } else if (response.tokenType === "access_token") {
+ console.log('access_token acquired at: ' + new Date().toString());
+ updateUI(response);
+ accessTokenButtonPopup.style.display = 'none';
+ accessTokenButtonRedirect.style.display = 'none';
+ } else {
+ console.log("token type is:" + response.tokenType);
+ }
+ }
+}
+
+// Redirect: once login is successful and redirects with tokens, call Graph API
+if (myMSALObj.getAccount() && !myMSALObj.isCallback(window.location.hash)) {
+ // avoid duplicate code execution on page load in case of iframe and Popup window.
+ showWelcomeMessage(myMSALObj.getAccount());
+}
+
+function signIn(method) {
+ signInType = isIE ? "loginRedirect" : method;
+ if (signInType === "loginPopup") {
+ myMSALObj.loginPopup(loginRequest)
+ .then(loginResponse => {
+ console.log(loginResponse);
+ if (myMSALObj.getAccount()) {
+ showWelcomeMessage(myMSALObj.getAccount());
+ }
+ }).catch(function (error) {
+ console.log(error);
+ });
+ } else if (signInType === "loginRedirect") {
+ myMSALObj.loginRedirect(loginRequest)
+ }
+}
+
+function signOut() {
+ myMSALObj.logout();
+}
+
+function getAccessTokenPopup() {
+ if (myMSALObj.getAccount()) {
+ myMSALObj.acquireTokenPopup(loginRequest).then(response => {
+ updateUI(response);
+ accessTokenButtonPopup.style.display = 'none';
+ accessTokenButtonRedirect.style.display = 'none';
+ }).catch(error => {
+ console.log(error);
+ });
+ }
+}
+
+function getAccessTokenRedirect() {
+ if (myMSALObj.getAccount()) {
+ myMSALObj.acquireTokenRedirect(loginRequest);
+ }
+}
+
+function getAccessTokenSilent() {
+ if (myMSALObj.getAccount()) {
+ myMSALObj.acquireTokenSilent(loginRequest).then(response => {
+ updateUI(response);
+ accessTokenButtonPopup.style.display = 'none';
+ accessTokenButtonRedirect.style.display = 'none';
+ }).catch(error => {
+ console.log(error);
+ })
+ }
+}
\ No newline at end of file
diff --git a/samples/msal-core-samples/VanillaJSTestApp/app/adfs/authConfig.js b/samples/msal-core-samples/VanillaJSTestApp/app/adfs/authConfig.js
new file mode 100644
index 0000000000..99d20b6c77
--- /dev/null
+++ b/samples/msal-core-samples/VanillaJSTestApp/app/adfs/authConfig.js
@@ -0,0 +1,18 @@
+// Config object to be passed to Msal on creation
+const msalConfig = {
+ auth: {
+ clientId: "57448aa1-9515-4176-a106-5cb9be8550e1",
+ authority: "https://fs.msidlab8.com/adfs/",
+ knownAuthorities: ["fs.msidlab8.com"]
+ },
+ cache: {
+ cacheLocation: "localStorage", // This configures where your cache will be stored
+ storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
+ }
+};
+
+// Add here scopes for id token to be used at MS Identity Platform endpoints.
+const loginRequest = {
+ scopes: ["openid", "profile"],
+ forceRefresh: false // Set this to "true" to skip a cached token and go to the server to get a new token
+};
diff --git a/samples/msal-core-samples/VanillaJSTestApp/app/adfs/index.html b/samples/msal-core-samples/VanillaJSTestApp/app/adfs/index.html
new file mode 100644
index 0000000000..abef0cd5fe
--- /dev/null
+++ b/samples/msal-core-samples/VanillaJSTestApp/app/adfs/index.html
@@ -0,0 +1,73 @@
+
+
+