Hi @Artem Shaturskyi
Welcome to the Microsoft Q&A Platform.
Thank you for reaching out, & I hope you are doing well.
Play your video files using the Storage Account Static Website with Entra ID authentication
by following the steps below.
- Create an app registration by navigating to
Microsoft EntraID > App registrations > New registrations.
- Add the redirect URL as
static website endpoint url
andlocalhost url
below.
- Enable the tokens for auto-authorization in application.
- Configure the storage account with
Entra ID authentication
as below.
- Configure CORS settings with required permissions in storage account.
- Configure the container access level to Private.
Storage account Static Website Url
Upload the index.html file below into the $web
container, and make sure to replace it with your Application ID, Tenant ID, and Storage Website URL.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secure Video Gallery</title>
<script src="https://alcdn.msauth.net/browser/2.29.0/js/msal-browser.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
}
#video-list {
margin-top: 20px;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.video-item {
cursor: pointer;
padding: 10px;
border: 1px solid #ccc;
margin: 5px;
display: inline-block;
background-color: #f9f9f9;
width: 200px;
text-align: center;
}
.video-item:hover {
background-color: #ddd;
}
video {
width: 80%;
margin-top: 20px;
border: 1px solid black;
}
#logout-btn {
display: none;
margin-top: 10px;
background-color: red;
color: white;
border: none;
padding: 10px;
cursor: pointer;
}
#auth-message {
margin-top: 15px;
font-weight: bold;
color: green;
display: none;
}
</style>
</head>
<body>
<h2>Secure Video Gallery</h2>
<button id="login-btn" onclick="signIn()">Sign in with Entra ID</button>
<button id="logout-btn" onclick="signOut()">Sign Out</button>
<div id="auth-message"></div>
<div id="video-list">Please sign in to view videos.</div>
<video id="video-player" controls crossorigin="anonymous" preload="auto">
Your browser does not support the video tag.
</video>
<script>
// Azure Entra ID Authentication Configuration
const msalConfig = {
auth: {
clientId: "2487c2f8-xxxxxxxxxxxxx-136163cc3502", // Replace with your Azure AD App Client ID
authority: "https://login.microsoftonline.com/9329c02a-4050-xxxxxxxxxx-b6e37b19af6d", // Replace with your Tenant ID
redirectUri: "https://vediostream.z13.web.core.windows.net" // Static Website URL
}
};
const msalInstance = new msal.PublicClientApplication(msalConfig);
const storageScope = "https://storage.azure.com/.default";
const blobListUrl = "https://vediostream.blob.core.windows.net/$web?restype=container&comp=list";
function updateUI(isAuthenticated) {
document.getElementById("login-btn").style.display = isAuthenticated ? "none" : "inline-block";
document.getElementById("logout-btn").style.display = isAuthenticated ? "inline-block" : "none";
document.getElementById("auth-message").style.display = isAuthenticated ? "block" : "none";
document.getElementById("auth-message").innerText = isAuthenticated ? "✅ Authentication successful." : "";
}
async function signIn() {
try {
const response = await msalInstance.loginPopup({ scopes: [storageScope] });
console.log("✅ Signed in:", response.account);
updateUI(true);
fetchVideos();
} catch (error) {
console.error("🔴 Login failed:", error);
document.getElementById("video-list").innerHTML = `<p>Login failed. Please try again.</p>`;
}
}
async function signOut() {
try {
await msalInstance.logoutPopup();
console.log("✅ Signed out");
updateUI(false);
document.getElementById("video-list").innerHTML = `<p>Please sign in to view videos.</p>`;
} catch (error) {
console.error("🔴 Logout failed:", error);
}
}
async function fetchAADToken() {
const account = msalInstance.getAllAccounts()[0];
if (!account) throw new Error("User is not authenticated.");
const tokenResponse = await msalInstance.acquireTokenSilent({
scopes: [storageScope],
account: account
});
if (!tokenResponse || !tokenResponse.accessToken) {
throw new Error("🔴 Failed to acquire AAD token.");
}
console.log("✅ AAD Access Token Acquired");
return tokenResponse.accessToken;
}
async function fetchVideos() {
try {
const accessToken = await fetchAADToken();
const response = await fetch(blobListUrl, {
method: "GET",
headers: {
"Authorization": `Bearer ${accessToken}`,
"x-ms-version": "2020-06-12",
"Accept": "application/xml"
}
});
if (!response.ok) throw new Error(`🔴 HTTP error! Status: ${response.status}`);
const text = await response.text();
console.log("🔹 Blob XML Response:", text);
const parser = new DOMParser();
const xml = parser.parseFromString(text, "application/xml");
const blobs = xml.getElementsByTagName("Blob");
let videoList = document.getElementById("video-list");
videoList.innerHTML = "";
let videoFound = false;
for (let i = 0; i < blobs.length; i++) {
let fileName = blobs[i].getElementsByTagName("Name")[0].textContent;
if (fileName.toLowerCase().endsWith(".mp4")) {
videoFound = true;
let videoItem = document.createElement("div");
videoItem.className = "video-item";
videoItem.textContent = fileName;
videoItem.onclick = function () {
playVideoSecurely(fileName);
};
videoList.appendChild(videoItem);
}
}
if (!videoFound) {
videoList.innerHTML = "<p>No videos found.</p>";
}
} catch (error) {
console.error("🔴 Error fetching video list:", error);
document.getElementById("video-list").innerHTML = `<p>Error loading videos. Please try again later.</p>`;
}
}
async function playVideoSecurely(fileName) {
try {
console.log(`🔹 Fetching video: ${fileName}`);
const accessToken = await fetchAADToken();
const fileUrl = `https://vediostream.blob.core.windows.net/$web/${encodeURIComponent(fileName)}`;
const response = await fetch(fileUrl, {
method: "GET",
headers: {
"Authorization": `Bearer ${accessToken}`,
"x-ms-version": "2020-06-12"
}
});
if (!response.ok) throw new Error(`🔴 HTTP error! Status: ${response.status}`);
const videoBlob = await response.blob();
const objectUrl = URL.createObjectURL(videoBlob);
let videoPlayer = document.getElementById("video-player");
// Remove previous sources to force refresh
videoPlayer.innerHTML = "";
let sourceTag = document.createElement("source");
sourceTag.src = objectUrl;
sourceTag.type = "video/mp4";
videoPlayer.appendChild(sourceTag);
videoPlayer.load();
videoPlayer.play();
console.log("✅ Video Loaded Securely");
} catch (error) {
console.error("🔴 Error loading video:", error);
alert("Error loading video. Please try again.");
}
}
</script>
</body>
</html>
Once you have completed all the steps, try accessing the static website URL in a browser. You will see the page as shown below.
Azure AD authentication page
Here is the result after signing in with Entra ID authentication.
Note: Make sure to assign the required role to access the Blob, Like Storage Blob Data Contributor
Here is the result if someone without the required role tries to access it.
If you want to access the static website URL within a private network, you can enable a Private Endpoint in the Storage Account and disable public access in the firewall.
Reference: Use private endpoints for Azure Storage
I hope this helps to resolve your issue.
Please don’t forget to close the thread by clicking "Accept the answer" wherever the information provided helps you, as this can be beneficial to other community members.