cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
Anonymous
Not applicable

How to configure SSO in PVA?

Hi,

 

I am trying to connect SSO in PVA on the Sharepoint website. I see the below error on the chrome console.

p1.png

I see a syntax error from the below line of code. I am following the SSO configuration by the doc provided below: "https://docs.microsoft.com/en-us/power-virtual-agents/configure-sso"

 

The below code is from the doc.

 

 var userID = clientApplication.account?.accountIdentifier != null ? ("Your-customized-prefix-max-20-characters" + clientApplication.account.accountIdentifier).substr(0,64) : (Math.random().toString() + Date.now().toString().substr(0,64)

 

I had posted by query before as well but no luck.. https://powerusers.microsoft.com/t5/General/How-to-configure-Single-Sign-On-in-PVA-with-Sharepoint-a...

 

Can anyone please help me out here?

 

Regards,

Hemanth

36 REPLIES 36
Anonymous
Not applicable

Hi @BoLi ,

 

Thanks a lot for responding back. I am able to achieve SSO using the code provided on github. I have few concerns regarding how the PVA is working from the code.

I have added two button on my Sharepoint Home Page.

 

1 for PVA to pop-up on the Home Page by clicking the button Power Virtual Agent the other button for Login as per the code from github.

 

I am able to achieve SSO only when i click on the login button which is from the github code. If i try accessing to PVA by directly clicking the button Power Virtual Agent. It asks for the login prompt even if i have login to Sharepoint Home Page which is the redirect URI that was added on the Azure SSO App registration. 

REF::

e1.png

When clicked on the button Log In it displays a new window of the existing Sharepoint homepage which doesn't asks for login as i have already login to the home page. Please refer the below snapshot. 

e4.png

 

Below is the snapshot of the PVA directly sign in without asking for login prompt. This works only when i have already clicked on the Login button that is added on my Sharepoint homepage provided form the github code, else if i click on the Power Virtual Agent button directly without accessing the Login button it gives me a login prompt.

e3.png

 

Ideally what i am trying to achieve is PVA has to login automatically when i have already login to my SharePoint home page. I don't want it to work on the basis of clicking on the Login button again even after i have logged to my SharePoint home page.

 

Can this be achieved? Thanks in advance.

 

Regards,

Hemanth 

Thanks Hemanth,

 

Still, you need to debug the code and check which step failed. From your descirption, it sounds like you didn't pass the initial login token to AAD to exchange for an On-behalf-of token. 

 

To clarify, SSO currently only work for AAD authentication.  if your own website use AAD to handle logging in, when your customer logged in to your website, you should be able to get a login token issued by AAD and you will need to use that token to exchange for an OBO token and pass to PVA backend to complete sign-in process.

Hello,

 

Sorry to dig up this post but I've been trying to configure SSO for our use and while I am trying to use the github example it's still not working as intended (also not throwing errors).  Here's the code, which is mostly from the github page.  Any recommendations would be appreciated.

 

@page
@model Bot.Website.IndexModel
@{
    ViewData["Title"] = "Home";
}

<!--Home page, currently the only page.  Displays some helpful links and the embedded bot in an iframe.-->
<div class="text-center">
    <h1 class="display-4"><img src="~/assets/icon-image.png" alt="" height="50" width="50" /> (removed)</h1>
</div>
<div class="row row-main">
    <div class="row-webchat" id="webchat">
        <!--https://docs.microsoft.com/en-us/power-virtual-agents/configure-bot-greeting-->
        <!--Adding code to have the bot start the greeting without a prompt-->
        <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
        <script type="text/javascript" src="https://alcdn.msauth.net/lib/1.4.0/js/msal.js"></script>
        <script type="text/javascript" src="~/lib/azure/storage-blob/browser/azure-storage.blob.min.js"></script>
        <script type="text/javascript">
            if (typeof Msal === 'undefined') document.write(unescape("%3Cscript src='https://alcdn.msftauth.net/lib/1.2.0/js/msal.js' type='text/javascript' %3E%3C/script%3E"));
        </script>
    </div>
   

<script>

    function getOAuthCardResourceUri(activity) {
        if (activity &&
            activity.attachments &&
            activity.attachments[0] &&
            activity.attachments[0].contentType === 'application/vnd.microsoft.card.oauth' &&
            activity.attachments[0].content.tokenExchangeResource) {
            // asking for token exchange with AAD

            return activity.attachments[0].content.tokenExchangeResource.uri;
        }
    }

    function exchangeTokenAsync(resourceUri) {
        let user = clientApplication.getAccount();
        if (user) {
            let requestObj = {
                scopes: [resourceUri]
            };
            return clientApplication.acquireTokenSilent(requestObj)
                .then(function (tokenResponse) {
                    return tokenResponse.accessToken;
                })
                .catch(function (error) {
                    console.log(error);
                });
        }
        else {
            return Promise.resolve(null);
        }
    }

    async function fetchJSON(url, options = {}) {
        const res = await fetch(url, {
            ...options,
            headers: {
                ...options.headers,
                accept: 'application/json'
            }
        });

        if (!res.ok) {
            throw new Error(`Failed to fetch JSON due to ${res.status}`);
        }

        return await res.json();
    }
</script>

<script>
    var clientApplication;
    (function () {
        var msalConfig = {
            auth: {
                // Client/tenant ID from (removed)

                clientId: '(removed)',
                authority: '(removed)'
            },
            cache: {
                cacheLocation: 'localStorage',
                storeAuthStateInCookie: false
            }
        };
        if (!clientApplication) {
            clientApplication = new Msal.UserAgentApplication(msalConfig);
        }
    }());

    (async function main() {

    // Bot ID - prod environment = (removed)
    // Bot ID - test environment = (removed)
    // TODO:  Set up prod and dev as variables

    var BOT_ID = "(removed)";

    var theURL = "https://powerva.microsoft.com/api/botmanagement/v1/directline/directlinetoken?botId=" + BOT_ID;

    //once this notifyMessage is checked means the conversationId variable is initialized, could set its value
    var notifyMessage = "(removed)";

    // Note that the prefix (cosine-es-bot) has to be 20 characters and the entire user ID cannot be more than 64 characters
    var userId = clientApplication.account?.accountIdentifier != null ?
        ("(removed)" + clientApplication.account.accountIdentifier).substr(0, 64)
        : (Math.random().toString() + Date.now().toString()).substr(0, 64);

    const { token } = await fetchJSON(theURL);
    const conversationId = token.conversationId;
    const directLine = window.WebChat.createDirectLine({ token });
    const store = WebChat.createStore({}, ({ dispatch }) => next => action => {
        const { type } = action;
        if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
            dispatch({
                type: 'WEB_CHAT/SEND_EVENT',
                payload: {
                    name: 'startConversation',
                    type: 'event',
                    value: { text: "hello" }
                }
            });
            return next(action);
        }
        // Make sure to add in the conversationId work that Allen did
        if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
            if (String(action.payload.activity.text).toLowerCase() === notifyMessage) {
                // the bot.conversationId has been initialized through the "Init conversationId" flow
                // set the bot global variable value through dispatch "SEND_EVENT"
                // For details about setting variables externally: see the link:
                // docs.microsoft.com/en-us/power-virtual-agents/authoring-variables-bot#set-a-bot-variables-value-from-external-sources
                dispatch({
                    type: "WEB_CHAT/SEND_EVENT",
                    payload: {
                        name: "pvaSetContext",
                        value: {
                            "conversationId": conversationId
                        }
                    }
                });

            }
            const activity = action.payload.activity;
            let resourceUri;
            if (activity.from && activity.from.role === 'bot' &&
                (resourceUri = getOAuthCardResourceUri(activity))) {
                exchangeTokenAsync(resourceUri).then(function (token) {
                    if (token) {
                        directLine.postActivity({
                            type: 'invoke',
                            name: 'signin/tokenExchange',
                            value: {
                                id: activity.attachments[0].content.tokenExchangeResource.id,
                                connectionName: activity.attachments[0].content.connectionName,
                                token
                            },
                            "from": {
                                id: userId,
                                name: clientApplication.account.name,
                                role: "user"
                            }
                        }).subscribe(
                            id => {
                                if (id === 'retry') {
                                    // bot was not able to handle the invoke, so display the oauthCard
                                    return next(action);
                                }
                                // else: tokenexchange successful and we do not display the oauthCard
                            },
                            error => {
                                // an error occurred to display the oauthCard
                                return next(action);
                            }
                        );
                        return;
                    }
                    else {
                        return next(action);
                    }
                });
            }
            else {
                return next(action);
            }
        }
        else {
            return next(action);
        }
    });

    const styleOptions = {
        // Add styleOptions to customize Web Chat canvas
        hideUploadButton: true
    };

    window.WebChat.renderWebChat(
        {
            directLine: directLine,
            store,
            userID: userId,
            styleOptions
        },
        document.getElementById('webchat')
    );
})().catch(err => console.error("An error occurred: " + err));
</script>
Anonymous
Not applicable

Hi @PaulCullivan 

 

The sample code provided on github works fine if you have configured the authentication part as per the doc provided for authentication and SSO. I am able to achieve this only when i click on the login button that is from the code. 

 

Regards,

Hemanth

Anonymous
Not applicable

Hi @BoLi ,

 

As I am trying to debug the code and find what is going wrong it redirects me to different CDN and files that is involved from the code provided on the github. I am not able to figure out what's going wrong here because of it, Is there anyway if the below code which is used for login button can be configured for the Power Virtual Agent button which is used to pop-up the chatbot for which I am using on the code to work without asking for the user to login I just want it to be authenticated directly without the pop-up showing up for login . Any help me much appreciated. Thanks in advance.

 

Login button code from github

 

<button id="login" name="login" onclick="onSignInClick()" style="float: right;background-color: aliceblue;">Log In</button>

function onSignin(idToken) {
      let user = clientApplication.getAccount();
      document.getElementById("userName").innerHTML = "Currently logged in as " + user.name;
      let requestObj1 = {
	scopes: ["user.read", 'openid', 'profile']
      };
    }

    function onSignInClick() {
      let requestObj = {
	scopes: ["user.read", 'openid', 'profile']
      };

      clientApplication.loginPopup(requestObj).then(onSignin).catch(function (error) {console.log(error) });
    }

 

 

Below is the code I am using.

 

 

<!DOCTYPE html>
<html>
<head>
  <title>Virtual Agent</title> 
  <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
  <script type="text/javascript" src="https://alcdn.msauth.net/lib/1.2.0/js/msal.js"></script>
  <script src="https://unpkg.com/@azure/storage-blob@10.3.0/browser/azure-storage.blob.min.js"
  integrity="sha384-fsfhtLyVQo3L3Bh73qgQoRR328xEeXnRGdoi53kjo1uectCfAHFfavrBBN2Nkbdf"
  crossorigin="anonymous"></script>
  <script type="text/javascript">
  if (typeof Msal === 'undefined') document.write(unescape("%3Cscript src='https://alcdn.msftauth.net/lib/1.2.0/js/msal.js' type='text/javascript' %3E%3C/script%3E"));
  </script>

  <style>
      
	html, body 
	{
	  height: 100%;
    }

    body 
	{
	  margin: 0;
    }
	
	.modal 
	{
      display: none; /* Hidden by default */
      position: fixed; /* Stay in place */
      z-index: 1; /* Sit on top */
      padding-top: 100px; /* Location of the box */
      left: 0;
      top: 0;
      width: 100%; /* Full width */
      height: 100%; /* Full height */
      overflow: auto; /* Enable scroll if needed */
      background-color: rgb(0,0,0); /* Fallback color */
      background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
    }
	
	.modal-content 
	{
      background-color: #fefefe;
      margin: auto;
      padding: 10px;
      border: 1px solid #888;
      width: 500px;
      height: 575px;
    }
    .close 
	{
      color: black;
      float: right;
      font-size: 28px;
      font-weight: bold;
    }

    .close:hover,
    .close:focus 
	{
      color: #000;
      text-decoration: none;
      cursor: pointer;
    }
	
    .main 
	{
	  margin: 18px;
	  border-radius: 4px;
    }

    div[role="form"]
	{
	  background-color: #3392FF;
    }

    #webchat 
	{
	  position: center;
      height: 530px;
      width: 100%;
      top: 60px;
      overflow: hidden;
    }
	#heading 
	{
	  padding-bottom: 5px;
	}

    h1 
	{
      font-size: 14px;
      font-family: Segoe UI;
      font-style: normal;
      font-weight: 600;
      font-size: 14px;
      line-height: 20px;
      color: #F3F2F1;
      letter-spacing: 0.005em;
      display: table-cell;
      vertical-align: middle;
      padding: 13px 0px 0px 20px;
    }

	#login 
	{
      position: fixed;
	  margin-left: 150px;
	}
	
    .span
	{
      font-weight: bold;
    }
    
	#myBtn 
	{
      position: fixed;
	  float:right;
      outline: none;
	  width:60px;
	  height:80px;
	  margin:auto auto auto 10px;
    }
	button:hover
	{
	  background-color: transparent;
	}   

  </style>

</head>
<body>
	
	<button id="myBtn" type="button">Power Virtual Agent</button>
	<button id="login" name="login" onclick="onSignInClick()" style="background-color: aliceblue;">Log In</button>

	<div id="myModal" class="modal">
		<div class="modal-content" style=" background-color: #FFD933">
			<span class="close">&times;</span>
			<div id="chatwindow">
				<div id="heading">
					<img src="https://kennametal.sharepoint.com/sites/testing/KE/project/SiteAssets/kmt_logo.png" width="42" height="30" alt="KMT-logo">
					<span class="span"><strong>Virtual Agent</strong></span>
				</div>
				<div id="webchat"></div>
			</div>
		</div>
	</div>

	<!--Button code begins here-->
	<script>
		
		var modal = document.getElementById("myModal");
		var btn = document.getElementById("myBtn");
		var span = document.getElementsByClassName("close")[0];

		btn.onclick = function () {
			onSignInClick();
			modal.style.display = "block";
		}

		span.onclick = function () {
			modal.style.display = "none";
		}

		window.onclick = function (event) {
			if (event.target == modal) {
				modal.style.display = "none";
			}
		}
	</script>
	<!--Button code ends here-->

	<script>
		function onSignin(idToken) {
			let user = clientApplication.getAccount();
			document.getElementById("userName").innerHTML = "Currently logged in as " + user.name;
			let requestObj1 = {
				scopes: ["user.read", 'openid', 'profile']
			};
		}

		function onSignInClick() {
			alert("Inside onSignInClick function");
			debugger;
			let requestObj = {
				scopes: ["user.read", 'openid', 'profile']
			};
			debugger;
			clientApplication.loginPopup(requestObj).then(onSignin).catch(function (error) { console.log(error) });
		}
		

		function getOAuthCardResourceUri(activity) {
			if (activity &&
				activity.attachments &&
				activity.attachments[0] &&
				activity.attachments[0].contentType === 'application/vnd.microsoft.card.oauth' &&
				activity.attachments[0].content.tokenExchangeResource) {
				// asking for token exchange with AAD
				return activity.attachments[0].content.tokenExchangeResource.uri;
			}
		}

		function exchangeTokenAsync(resourceUri) {
			let user = clientApplication.getAccount();
			if (user) {
				let requestObj = {
					scopes: [resourceUri]
				};
				return clientApplication.acquireTokenSilent(requestObj)
					.then(function (tokenResponse) {
						return tokenResponse.accessToken;
					})
					.catch(function (error) {
						console.log(error);
					});
			}
			else {
				return Promise.resolve(null);
			}
		}

		async function fetchJSON(url, options = {}) {
			const res = await fetch(url, {
				...options,
				headers: {
					...options.headers,
					accept: 'application/json'
				}
			});

			if (!res.ok) {
				throw new Error(`Failed to fetch JSON due to ${res.status}`);
			}
			return await res.json();
		}
	</script>

	<script>
	
		const styleOptions = {
		botAvatarInitials: 'BT',
		userAvatarInitials: 'UR',
		accent: '#00809d',
		botAvatarBackgroundColor: "#FFFFFF",
		userAvatarBackgroundColor:"#FFFFFF",
		botAvatarImage:"<BOT_IMAGE>",
		userAvatarImage:"<USER_IMAGE>",
		hideUploadButton: true,
		};
	
		var clientApplication;
		
		(function () {
		debugger;
			var msalConfig = {
				auth: {
					clientId: '<CLIENT_ID>',
					authority: 'https://login.microsoftonline.com/<DIRECTORY_ID>'
				},
				cache: {
					cacheLocation: 'localStorage',
					storeAuthStateInCookie: false
				}
			};
			if (!clientApplication) {
				debugger;
				clientApplication = new Msal.UserAgentApplication(msalConfig);	
			}
		}());


		(async function main() {
			debugger;
			// Add your BOT ID below
			var BOT_ID = "<BOT_ID>";
			var theURL = "https://powerva.microsoft.com/api/botmanagement/v1/directline/directlinetoken?botId=" + BOT_ID;

			var userId = clientApplication.account?.accountIdentifier != null ?
				("You-customized-prefix" + clientApplication.account.accountIdentifier).substr(0, 64)
				: (Math.random().toString() + Date.now().toString()).substr(0, 64);
			debugger;
			
			const { token } = await fetchJSON(theURL);
			const directLine = window.WebChat.createDirectLine({ token });
			const store = WebChat.createStore({}, ({ dispatch }) => next => action => {
				const { type } = action;
				if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
					dispatch({
						type: 'WEB_CHAT/SEND_EVENT',
						payload: {
							name: 'startConversation',
							type: 'event',
							value: { text: "hello" }
						}
					});
					return next(action);
				}
				if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
					const activity = action.payload.activity;
					let resourceUri;
					if (activity.from && activity.from.role === 'bot' &&
						(resourceUri = getOAuthCardResourceUri(activity))) {
						exchangeTokenAsync(resourceUri).then(function (token) {
							if (token) {
								directLine.postActivity({
									type: 'invoke',
									name: 'signin/tokenExchange',
									value: {
										id: activity.attachments[0].content.tokenExchangeResource.id,
										connectionName: activity.attachments[0].content.connectionName,
										token
									},
									"from": {
										id: userId,
										name: clientApplication.account.name,
										role: "user"
									}
								}).subscribe(
									id => {
										if (id === 'retry') {
											// bot was not able to handle the invoke, so display the oauthCard
											return next(action);
										}
										// else: tokenexchange successful and we do not display the oauthCard
									},
									error => {
										// an error occurred to display the oauthCard
										return next(action);
									}
								);
								return;
							}
							else
								return next(action);
						});
					}
					else
						return next(action);
				}
				else
					return next(action);
			});

			

			window.WebChat.renderWebChat(
				{
					directLine: directLine,
					store,
					userID: userId,
					styleOptions
				},
				document.getElementById('webchat')
			);
		})().catch(err => console.error("An error occurred: " + err));
	</script>
</body>
</html>

 

 

Regards,

Hemanth

 

Hey HemanthN, thanks for the response.

 

We went through the documentation for authentication over the weekend:

https://docs.microsoft.com/en-us/power-virtual-agents/configure-sso

 

We confirmed that the production bot was working correctly.  I relaunched the test bot (which has the code mentioned above) and I can see that the user is logged in correctly, but this always fails and the oauthCard always gets displayed.  Is there something with how the request is being passed that's causing the problem?

 

sso.png

Hi, this can be achieved. 

what you should do is when the login button on your home page was clicked and user successfully logged in to AAD(AAD is a must because sso only support AAD V2 type IDP right now), there will be a login token return from AAD back to your home page, you should use the token and then call AAD again to exchange this for a OBO token and then put OBO token as part of invoke activity and send it to PVA. This is what the github sso sample domo does today.

Thanks for the response, and sorry for the delay.

I got the button working and thanks for the tip.  However, when we saw the post on SSO we were assuming that it was for users in the chat window that could log in without having to resort to the oauthCard.

https://docs.microsoft.com/en-us/power-virtual-agents/configure-sso

 

Do you know why the button works and the login in the script doesn't?

Whoops, sorry.  Specifically I am referring to the below.  As I mentioned earlier I was trying to get this to work but no matter what we keep failing at id === retry every time we pass this through.  Thanks again, really appreciate it.

 

const activity = action.payload.activity;
            let resourceUri;
            if (activity.from && activity.from.role === 'bot' &&
                (resourceUri = getOAuthCardResourceUri(activity))) {
                exchangeTokenAsync(resourceUri).then(function (token) {
                    if (token) {
                        directLine.postActivity({
                            type: 'invoke',
                            name: 'signin/tokenExchange',
                            value: {
                                id: activity.attachments[0].content.tokenExchangeResource.id,
                                connectionName: activity.attachments[0].content.connectionName,
                                token
                            },
                            "from": {
                                id: userId,
                                name: clientApplication.account.name,
                                role: "user"
                            }
                        }).subscribe(
                            id => {
                                if (id === 'retry') {
                                    // bot was not able to handle the invoke, so display the oauthCard
                                    return next(action);
                                }
                                // else: tokenexchange successful and we do not display the oauthCard
                            },
                            error => {
                                // an error occurred to display the oauthCard
                                return next(action);
                            }
                        );
                        return;
                    }
                    else {
                        return next(action);
                    }

So in looking into this I can see that we're getting a 412 error and that I am getting href = undefined in monitorIframeForHash.  As far as I can tell the authentication settings for powerVA and the app registration appear to be valid.  The bot is logging people in as expected live.  FWIW I am testing locally.  Couldn't upload a photo so here is where I get the error.

 

static monitorIframeForHash(contentWindow: Window, timeout: number, urlNavigate: string, logger: Logger): Promise<string> {
        return new Promise((resolve, reject) => {
            /*
             * Polling for iframes can be purely timing based,
             * since we don't need to account for interaction.
             */
            const nowMark = TimeUtils.relativeNowMs();
            const timeoutMark = nowMark + timeout;

            logger.verbose("monitorWindowForIframe polling started");

            const intervalId = setInterval(() => {
                if (TimeUtils.relativeNowMs() > timeoutMark) {
                    logger.error("monitorIframeForHash unable to find hash in url, timing out");
                    logger.errorPii(`monitorIframeForHash polling timed out for url: ${urlNavigate}`);
                    clearInterval(intervalId);
                    reject(ClientAuthError.createTokenRenewalTimeoutError());
                    return;
                }

                let href;

                try {
                    /*
                     * Will throw if cross origin,
                     * which should be caught and ignored
                     * since we need the interval to keep running while on STS UI.
                     */
                    href = contentWindow.location.href;
                } catch (e) {}

                if (href && UrlUtils.urlContainsHash(href)) {
                    logger.verbose("monitorIframeForHash found url in hash");
                    clearInterval(intervalId);
                    resolve(contentWindow.location.hash);
                } 
            }, WindowUtils.POLLING_INTERVAL_MS);
        });
    }

 

Helpful resources

Announcements

Super User of the Month | Chris Piasecki

In our 2nd installment of this new ongoing feature in the Community, we're thrilled to announce that Chris Piasecki is our Super User of the Month for March 2024. If you've been in the Community for a while, we're sure you've seen a comment or marked one of Chris' helpful tips as a solution--he's been a Super User for SEVEN consecutive seasons!   Since authoring his first reply in April 2020 to his most recent achievement organizing the Canadian Power Platform Summit this month, Chris has helped countless Community members with his insights and expertise. In addition to being a Super User, Chris is also a User Group leader, Microsoft MVP, and a featured speaker at the Microsoft Power Platform Conference. His contributions to the new SUIT program, along with his joyous personality and willingness to jump in and help so many members has made Chris a fixture in the Power Platform Community.   When Chris isn't authoring solutions or organizing events, he's actively leading Piasecki Consulting, specializing in solution architecture, integration, DevOps, and more--helping clients discover how to strategize and implement Microsoft's technology platforms. We are grateful for Chris' insightful help in the Community and look forward to even more amazing milestones as he continues to assist so many with his great tips, solutions--always with a smile and a great sense of humor.You can find Chris in the Community and on LinkedIn. Thanks for being such a SUPER user, Chris! 🌠💪

Tuesday Tips: Community Ranks and YOU

TUESDAY TIPS are our way of communicating helpful things we've learned or shared that have helped members of the Community. Whether you're just getting started or you're a seasoned pro, Tuesday Tips will help you know where to go, what to look for, and navigate your way through the ever-growing--and ever-changing--world of the Power Platform Community! We cover basics about the Community, provide a few "insider tips" to make your experience even better, and share best practices gleaned from our most active community members and Super Users.   With so many new Community members joining us each week, we'll also review a few of our "best practices" so you know just "how" the Community works, so make sure to watch the News & Announcements each week for the latest and greatest Tuesday Tips!This Week: Community Ranks--Moving from "Member" to "Community Champion"   Have you ever wondered how your fellow community members ascend the ranks within our community? What sets apart an Advocate from a Helper, or a Solution Sage from a Community Champion? In today’s #TuesdayTip, we’re unveiling the secrets and sharing tips to help YOU elevate your ranking—and why it matters to our vibrant communities. Community ranks serve as a window into a member’s role and activity. They celebrate your accomplishments and reveal whether someone has been actively contributing and assisting others. For instance, a Super User is someone who has been exceptionally helpful and engaged. Some ranks even come with special permissions, especially those related to community management. As you actively participate—whether by creating new topics, providing solutions, or earning kudos—your rank can climb. Each time you achieve a new rank, you’ll receive an email notification. Look out for the icon and rank name displayed next to your username—it’s a badge of honor! Fun fact: Your Community Engagement Team keeps an eye on these ranks, recognizing the most passionate and active community members. So shine brightly with valuable content, and you might just earn well-deserved recognition! Where can you see someone’s rank? When viewing a post, you’ll find a member’s rank to the left of their name.Click on a username to explore their profile, where their rank is prominently displayed. What about the ranks themselves? New members start as New Members, progressing to Regular Visitors, and then Frequent Visitors.Beyond that, we have a categorized system: Kudo Ranks: Earned through kudos (teal icons).Post Ranks: Based on your posts (purple icons).Solution Ranks: Reflecting your solutions (green icons).Combo Ranks: These orange icons combine kudos, solutions, and posts. The top ranks have unique names, making your journey even more exciting! So dive in, collect those kudos, share solutions, and let’s see how high you can rank!  🌟 🚀   Check out the Using the Community boards in each of the communities for more helpful information!  Power Apps, Power Automate, Copilot Studio & Power Pages

Find Out What Makes Super Users So Super

We know many of you visit the Power Platform Communities to ask questions and receive answers. But do you know that many of our best answers and solutions come from Community members who are super active, helping anyone who needs a little help getting unstuck with Business Applications products? We call these dedicated Community members Super Users because they are the real heroes in the Community, willing to jump in whenever they can to help! Maybe you've encountered them yourself and they've solved some of your biggest questions. Have you ever wondered, "Why?"We interviewed several of our Super Users to understand what drives them to help in the Community--and discover the difference it has made in their lives as well! Take a look in our gallery today: What Motivates a Super User? - Power Platform Community (microsoft.com)

March User Group Update: New Groups and Upcoming Events!

  Welcome to this month’s celebration of our Community User Groups and exciting User Group events. We’re thrilled to introduce some brand-new user groups that have recently joined our vibrant community. Plus, we’ve got a lineup of engaging events you won’t want to miss. Let’s jump right in: New User Groups   Sacramento Power Platform GroupANZ Power Platform COE User GroupPower Platform MongoliaPower Platform User Group OmanPower Platform User Group Delta StateMid Michigan Power Platform Upcoming Events  DUG4MFG - Quarterly Meetup - Microsoft Demand PlanningDate: 19 Mar 2024 | 10:30 AM to 12:30 PM Central America Standard TimeDescription: Dive into the world of manufacturing with a focus on Demand Planning. Learn from industry experts and share your insights. Dynamics User Group HoustonDate: 07 Mar 2024 | 11:00 AM to 01:00 PM Central America Standard TimeDescription: Houston, get ready for an immersive session on Dynamics 365 and the Power Platform. Connect with fellow professionals and expand your knowledge. Reading Dynamics 365 & Power Platform User Group (Q1)Date: 05 Mar 2024 | 06:00 PM to 09:00 PM GMT Standard TimeDescription: Join our virtual meetup for insightful discussions, demos, and community updates. Let’s kick off Q1 with a bang! Leaders, Create Your Events!  Leaders of existing User Groups, don’t forget to create your events within the Community platform. By doing so, you’ll enable us to share them in future posts and newsletters. Let’s spread the word and make these gatherings even more impactful! Stay tuned for more updates, inspiring stories, and collaborative opportunities from and for our Community User Groups.   P.S. Have an event or success story to share? Reach out to us – we’d love to feature you!

Tuesday Tips: Community Blogs--A Great Place to Start

  It's TUESDAY, so it's time for an all-new TUESDAY TIP.    This ongoing series of posts is our way of communicating helpful things we've learned or shared that have helped members of the Community. Whether you're just getting started or you're a seasoned pro, Tuesday Tips will help you know where to go, what to look for, and navigate your way through the ever-growing--and ever-changing--world of the Power Platform Community! We cover basics about the Community, a few "insider tips" to make your experience even better, and share best practices gleaned from our most active community members and Super Users. Make sure to watch the News & Announcements each week for the latest and greatest Tuesday Tips!   THIS WEEK: COMMUNITY BLOGS One of the highlights of the Power Platform Community is the very active Community Blog. Whether you're working mostly with Power Apps, creating flows in Power Automate, unlocking the power of Copilot Studio, or building websites with Power Pages, each Community has its own, dedicated blog that is written by--and for--our Community members!When you have a question and aren't sure how to ask it, or when you're looking for a solution to a particularly vexing problem, what you're looking for may already have been written about by someone who has faced the issue--and found an answer! Our blogs are written by both Super User pros and by low-code rookies, because it doesn't matter how long you've been part of Power Platform or the Community. What matters is whether or not you have a solution that can be shared to people who really need the help.   With new blog posts released several times a week, you never know what answer you will find. And the blogs are a great place to discuss what works, share what you may have found yourself, and build connections with other Community members facing similar questions or concerns! We are so grateful for the awesome group of bloggers who share their tips, knowledge, and skills. It's been exciting to see so many new Community members join the blog since last fall.Check Out the Community Blogs Today: Power Apps Community BlogPower Automate Community BlogCopilot Studio Community BlogPower Pages Community Blog There's so much more you'll discover in the Community Blogs, and we hope you'll check them out today!  Interested in blogging? Click here & message your Community Managers today to get started.

February 2024 Community Newsletter

Welcome to our February Newsletter, where we highlight the latest news, product releases, upcoming events, and the amazing work of our outstanding Community members. If you're new to the Community, please make sure to follow the latest News & Announcements and check out the Community on LinkedIn as well! It's the best way to stay up-to-date in 2024 with all the news from across Microsoft Power Platform and beyond. Are you ready to "Leap" in to all we've got to share today?   COMMUNITY HIGHLIGHTS Check out the most active community members of the last month! These hardworking members post regularly, answer questions, kudos, and provide top solutions in their communities. We are so thankful for all your great work in January, and we can't wait to see who will be our most active members next month!   Power AppsPower AutomateCopilot StudioPower PagesWarrenBelzWarrenBelzPstork1saudali_25LaurensMPstork1stephenrobertLucas001AARON_ClbendincpaytonSurendran_RANBNived_NambiarMariamPaulachanNikhil2JmanriqueriosANBJupyter123rodger-stmmbr1606Agniusstevesmith27mandelaPhineastrice602AnnaMoyalanOOlashynBCLS776grantjenkinsExpiscornovusJcookSpongYeAARON_CManishSolankiapangelesPstork1ManishSolankiSanju1Fubar   There was a lot of activity in the Community in February! Did you miss anything? Here are just a few of the announcements and updates we shared: Super User Season 1 is HereFebruary 2024 User Group Update: Welcoming New GroupsCelebrating a New Season of Super UsersCheck out the February 2024 Dynamics NewsletterAnnouncing Copilot Cookbook GallerySuper User of the Month D. PoggemannTuesday Tips: Getting Started in the Community The best way to not miss them is to make sure you're subscribed to your community's News & Announcements. Subscribe today and don't miss anything next month! Power Apps News, Power Automate News, Copilot Studio News, Power Pages News Copilot Cookbook for Power Apps The all-new Copilot Cookbook is now available in the #PowerApps Community - offering a wide array of best practices on how to use Microsoft Copilot to develop and create in Power Apps.   The #CopilotCookbook is your new go-to resource when you need inspiration (or when you're stuck!) and aren't sure how to best partner with Copilot. So, whether you're looking for the best prompts or just want to know about responsible AI use, you can visit the Copilot Cookbook for regular, high-quality content that you can rely on. Our team will be reviewing posts using the new "Copilot " label to ensure we highlight and amplify the most relevant and recent content, so you're assured of high-quality content every time you visit. If you share a post that gets featured in the curated gallery, you'll get a PM in the Community to let you know!   The curated gallery is now ready for you to experience, so click the image below and check out the all-new Copilot Cookbook for Power Apps today. We can't wait to see what you "cook" up! 👨🍳       Power Platform Dev Weekly Celebrate 200th Episode Congratulations to Danish Naglekar, Anwesha Sharma, Matt Beard, Mark Carrington Carl Cookson and the team, as they celebrated the 200th episode of Power Platform Dev Weekly in February!   Click the image below to check out this landmark episode, featuring content from the likes of Nati Turtledove, Matthew Devaney, Inogic, Mohamed Ashiq Faleel, Mike Hartley, Nishant Rana, James Yumnam, Carl Cookson, Yannick Reekmans, Deepesh Somani, and many more.       "Get Started With" Power Platform Shorts Series This month we launched our new 'Get Started With' series on YouTube - a selection of sweet snapshots to keep you in the loop with all the latest Copilot trends that you can try out through advice at Microsoft Learn. Click the image below to check out the entire playlist so far, and don't forget to subscribe to our YouTube channel for all the latest updates.     UPCOMING EVENTS Canadian Power Platform Summit - Vancouver - 16th March 2024 Check out the first ever Canadian Power Platform Summit, which takes place at Microsoft Vancouver office on Saturday 16th March 2024! Get ready to immerse yourself in the ultimate Power Platform experience at the #CPPS24. This event is tailored for makers, developers, students and tech enthusiasts eager to explore the depths of Power Platform technologies. With sessions ranging from beginner-friendly to advanced-intermediate, this event offers a diverse range of insights for attendees of all levels.   There's a great range of speakers, including the likes of Lisa Crosbie, Matthew Devaney, Ulrikke Akerbæk, Oleksandr Olashyn, Mark Smith, Jake Harvey, Manju Gurjar, Adam Tobias, Mats Necker, Natasza Kosakowska, Linn Zaw Win, Salim Adamon, Tomas Prokop, Maxim Nikonov, and many more.   Great work by Chris Piasecki, Éric Sauvé, Nick Doelman, Scott Durow, Victor Dantas and the team for putting this amazing event together. So, whether you're a seasoned pro or a rising star, click the image below to join the Microsoft Community in Canada to gain practical insights, discover real-world examples, and take away actionable skills to boost your expertise.   Business Applications Launch Event - Virtual - 10th April 2024 Registration is now open for the Microsoft Business Applications Launch event which kicks off at 9am PST on Wednesday 10th April 2024. Join Microsoft product leaders and engineers for an in-depth look at the latest news and AI capabilities in Power Platform and #Dynamics365, featuring the likes of Charles Lamanna, Sangya Singh, Julie Strauss, Donald Kossmann, Lori Lamkin, Georg Glantschnig, Mala Anand, Jeff Comstock, and Mike Morton.     Microsoft Fabric - Las Vegas - 26-28th March 2024 Exciting times ahead for the inaugural #MicrosoftFabric Community Conference on March 26-28 at the MGM Grand in Las Vegas! The conference will cover all the latest in analytics, AI, databases, and governance across 150+ sessions, with guest speakers including Arun Ulag, Amir Netz, Jessica Hawk, Eric Boyd, Kim Manis, Adam Saxton, Patrick LeBlanc, Bob Ward, Wangui McKelvey, Wee Hyong T., Justyna Lucznik, Priya Sathy, Mehrnoosh Sameki, Rachel Shepard, Karthik Ravindran, Jason Himmelstein, and many more.   On-site there will be a special Community Lounge, interactive learning labs, plus you'll be able to 'Ask the Experts' all your questions to get help from data, analytics, and AI specialists, including community members and the Fabric Customer Advisory Team. Click the image below to find out more about the ultimate learning event for Microsoft Fabric!   If you'd like to learn how the latest advances in AI and how #MicrosoftCopilot can help you streamline your processes, click the image below to register today!       LATEST COMMUNITY BLOG ARTICLES Power Apps Community Blog Power Automate Community Blog Copilot Studio Community Blog Power Pages Community Blog Check out 'Using the Community' for more helpful tips and information: Power Apps, Power Automate, Copilot Studio, Power Pages

Users online (2,621)