{"id":274,"date":"2016-11-28T06:00:56","date_gmt":"2016-11-28T14:00:56","guid":{"rendered":"https:\/\/www.microsoft.com\/en-us\/power-platform\/blog\/power-apps\/custom-api-with-authentication\/"},"modified":"2025-06-11T08:16:34","modified_gmt":"2025-06-11T15:16:34","slug":"custom-api-with-authentication","status":"publish","type":"post","link":"https:\/\/www.microsoft.com\/en-us\/power-platform\/blog\/power-apps\/custom-api-with-authentication\/","title":{"rendered":"Guest Blog: Build Custom API on Microsoft Flow and PowerApps with Authentication"},"content":{"rendered":"
We came across a great blog post<\/a> by our colleague Tsuyoshi Matsuzaki from Microsoft Japan. Tsuyoshi Matsuzaki is a technical evangelist whose mission is educating and supporting ISV developers on Microsoft Azure, Office 365 , and other enterprise platforms.<\/p>\n Thanks Tsuyoshi, on behalf of the PowerApps team!<\/p>\n ———————————————————————————————-<\/p>\n The custom api enables you to connect your own web api (REST api) in Microsoft Flow (including SharePoint workflow) and PowerApps. You can connect Microsoft Flow and PowerApps with your in-house applications or unknown 3rd party (ISV) applications.<\/p>\n In this post I show you how to build and use the custom api, and in most cases the authentication is needed, then I also explain with real authentication scenario. (First I explain using Azure AD, and next I show you the other cases, such as Google account.)<\/p>\n In the first example, we use the Azure Active Directory (Azure AD)\u00a0 as the authentication provider with custom api. I don\u2019t describe how to build the web api secured by the Azure AD, but if you\u2019re using ASP.NET Web API, you just click [Change Authentication] button in the project creation wizard and set-up the Azure AD information. (See the following screen.)<\/p>\n If you\u2019re using other programming language, see \u201cHow to build API secured by Azure AD<\/a>\u201d (Japanese) in my previous post.<\/p>\n Note : You can also use the Azure App Service (API App) and [Authentication \/ Authorization] settings (so called \u201cEasy Auth\u201d) for every programming languages. Next you must prepare the swagger specification file (json file). The next is one of the swagger specification example. Especially, you must remember operationId value (the following \u201cValues_Get\u201d), because we use this operation in the PowerApps later.<\/p>\n In the swagger specification, you must add the following \u201csecurityDefinitions\u201d section, and set Azure AD authentication information as follows.<\/p>\n If you use Swashbuckle in your ASP.NET Web API project, you just insert the following code (bold font) in App_Start\\SwaggerConfig.cs.<\/p>\n In the case of Azure AD, the custom api proxy in the Microsoft Flow or PowerApps retrieves the access token for your web api resource, and calls your web api by setting this token in the http header. Note : If you have used the previous [Change Authentication] button in ASP.NET Web API, the web api app is already registered in Azure AD.<\/p>\n The following illustrates this.<\/p>\n When you register the custom api proxy (Azure AD app of Microsoft Flow or PowerApps side), you must add the following url (fixed value) as the redirect url. Both Microsoft Flow and PowerApps uses this redirect url, when processing OAuth.<\/p>\n Currently (in Nov 2016), the Azure AD v2 endpoint is not supported (but v1 only) for this scenario, and you must use the Azure Classic Portal (https:\/\/manage.windowsazure.com\/<\/a>), not Azure Ibiza Portal (https:\/\/portal.azure.com<\/a>). See the following screenshot.<\/p>\n Note : Strictly speaking, v2.0 endpoint (Azure AD v2 endpoint) is supported in the custom api. But, this proxy and web api flow (see the illustration above) is not supported for v2.0 endpoint. Now you\u2019re ready to use the custom api in Microsoft Flow and PowerApps. Here I show you the step of setting PowerApps.<\/p>\n Note : For the details of this procedure, please refer the official document \u201cRegister Custom APIs in PowerApps<\/a>\u201c.<\/p>\n First you login to PowerApps (https:\/\/web.powerapps.com\/<\/a>), and select [Connections] in the navigation, and click [New connection].<\/p>\n Select [Custom] tab and click [New custom API].<\/p>\n In the next window, upload the swagger specification file (json) previously created.<\/p>\n The swagger specification is parsed and the identity provider is auto-detected by the PowerApps. The connection settings of the custom api has done. Next you start to create the app in the PowerApps.<\/p>\n Click [New App] button, and select [Phone layout] in the [Blank app].<\/p>\n In the design window, select [Content] \u2013 [Data sources] menu.<\/p>\n The data source window is displayed in the right pane, and click [Add data source] button, and [New connection] button. Then the Azure AD sign-in UI is displayed, and you must enter your credential.<\/p>\n The custom api is inserted as the data source.<\/p>\n Let\u2019s test this custom api !<\/p>\n Please insert the button control into your app, and input the following expression as the button \u201cOnSelect\u201d function (fx). Note : You can use auto-correct or suggestions when you\u2019re writing functions.<\/p>\n Next you insert the text box, and set \u201cResultValue\u201d (the context variable previously created) in the text box function.<\/p>\n Push run button, and this app is launched in the web browser. In the backend, the following http request is called against your web api. Note : The \u201cX-Ms-Apim-Tokens\u201d header is also important, and I explain this later. (In the case of Azure AD, there\u2019s no need to use this token.)<\/p>\n This token (\u201cAuthorization\u201d header value) is the Azure AD access token itself. Then you can also get the access token for another resources in your web api by calling the following OAuth on_behalf_of flow. You can share your app to other people in the same organization. You can also use the OAuth 2.0 of Google, Facebook, Salesforce and other SaaS applications including the generic OAuth 2.0 providers. (see the official document \u201cRegister Custom APIs in Microsoft Flow<\/a>\u201c. The flow by API Key and Basic Authentication are also supported.)<\/p>\n Let\u2019s see the case of Google account.<\/p>\n Google and most providers are not having api registration, only client registration. (Except for the app context like api key.) Next is the swagger example for Google account settings. (see the bold font)<\/p>\n PowerApps (or Microsoft Flow) automatically detects Google account, and when you connect to the custom api, the Google account login is displayed as the following screenshot.<\/p>\n Next is the http request for your web api. Therefore you cannot verify this access token in your web api, but you can verify the login user instead of using X-Ms-Apim-Tokens<\/strong>. This token (X-Ms-Apim-Tokens) is the Base64 Url encoded value (see RFC 4648) of the following json string, and as you can see, the value includes the refresh token and id token of Google account. As a result, you can decode the id token value, and retrieve the user claims, verify the digital signature.<\/p>\n If your web api doesn\u2019t need the login user, you could use the api key instead.<\/p>\n ———————————————————————————————-<\/p>\n","protected":false},"excerpt":{"rendered":" Guest blog post from Tsuyoshi Matsuzaki, where he shows us how to build an use a custom api and the authentication with Azure AD and Google account<\/p>\n","protected":false},"author":100,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ms_queue_id":[],"ep_exclude_from_search":false,"_classifai_error":"","_classifai_text_to_speech_error":"","_alt_title":"","ms-ems-related-posts":[],"footnotes":""},"audience":[3378],"content-type":[],"job-role":[],"product":[3473],"property":[],"topic":[3421],"coauthors":[2098],"class_list":["post-274","post","type-post","status-publish","format-standard","hentry","audience-it-professional","product-power-apps","topic-application-modernization"],"yoast_head":"\nBuild your own web api<\/h3>\n
\nIn this case, your web api must handle the OAuth access token.<\/p>\n
<\/a><\/p>\n
\nSee \u201cAuthentication and authorization in Azure App Service<\/a>\u201d for details.<\/p>\n
<\/p>\n
\nIf you use ASP.NET Web API, you can insert \u201cSwashbuckle\u201d Nuget package and download this json by accessing http:\/\/{your root URL}\/swagger\/docs\/v1.<\/p>\n
<\/a><\/p>\n{\n \"swagger\": \"2.0\",\n \"info\": {\n \"version\": \"v1\",\n \"title\": \"TestApi01\"\n },\n \"host\": \"demo.azurewebsites.net\",\n \"schemes\": [\n \"https\"\n ],\n \"paths\": {\n \"\/api\/Values\/{id}\": {\n \"get\": {\n \"tags\": [\n \"Values\"\n ],\n \"operationId\": \"Values_Get\",\n \"consumes\": [\n ],\n \"produces\": [\n \"application\https://www.microsoft.com/json\",\n \"text\https://www.microsoft.com/json\",\n \"application\/xml\",\n \"text\/xml\"\n ],\n \"parameters\": [\n {\n \"name\": \"id\",\n \"in\": \"path\",\n \"required\": true,\n \"type\": \"integer\",\n \"format\": \"int32\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"OK\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n }\n },\n . . .\n }\n },\n \"definitions\": {\n },\n \"securityDefinitions\": {\n \"oauth2\": {\n \"type\": \"oauth2\",\n \"flow\": \"implicit\",\n \"authorizationUrl\": \"https:\/\/login.windows.net\/common\/oauth2\/authorize\",\n \"scopes\": {\n }\n }\n }<\/strong>\n}<\/pre>\npublic class SwaggerConfig\n{\n public static void Register()\n {\n var thisAssembly = typeof(SwaggerConfig).Assembly;\n GlobalConfiguration.Configuration\n .EnableSwagger(c =>\n {\n c.SingleApiVersion(\"v1\", \"TestApi01\");\n . . .\n c.OAuth2(\"oauth2\")\n .AuthorizationUrl(\"https:\/\/login.windows.net\/common\/oauth2\/authorize\")\n .Flow(\"implicit\")\n .Scopes(scopes =>\n {\n \/\/scopes.Add(\"xxxxx\", \"Some access to protected resources\");\n });<\/strong>\n })\n .EnableSwaggerUi(c =>\n {\n . . .\n });\n }\n}<\/pre>\nRegister APIs in Azure AD<\/h3>\n
\ni.e, you must register both the custom api proxy app and your web api app<\/strong> in the Azure AD, and set the permission between custom api proxy and your web api.<\/p>\n
<\/p>\nhttps:\/\/msmanaged-na.consent.azure-apim.net\/redirect<\/code><\/pre>\n
\nAnd you must set the custom api proxy\u2019s permissions for accessing your web api in the Azure Classic Portal. (You cannot set this permission and cannot see the resource id in the Ibiza portal today.)<\/p>\n
\nPlease refer the next Google scenario (flow) for the v2.0 endpoint.<\/p>\n
<\/a><\/p>\nHow to work (or use) in PowerApps<\/h3>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
\nYou must set some api information in the next window like the following screenshot. Note that this client id and secret is for the previous custom api proxy, not your web api. The Resource URL (the accessing scopes) is the ID\/URI of your web api, not the custom api proxy.<\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
\nYou can find the previously created custom api, and select (connect) that.<\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n
\nThis is calling the \u201cValuesGet\u201d method (see the previous \u201coperationId\u201d in the swagger file) in the custom api named \u201cTestApi01\u201d, and setting the string result in the context variable named \u201cResultValue\u201d.<\/p>\n
<\/a><\/p>\nUpdateContext( { ResultValue : TestApi01.ValuesGet(3) } )<\/pre>\n
<\/a><\/p>\n
\nWhen you push the button in the app, your web api is called by the PowerApps and the returned value is displayed in the text box.<\/p>\n
<\/a><\/p>\n
\nThen your web api can verify the token (the following \u201cAuthorization\u201d header value) and retrieve the claims. Please see\u00a0 \u201cProtect a Web API using Bearer tokens from Azure AD<\/a>\u201d for this programming when you\u2019re using ASP.NET Web API..<\/p>\nGET \/api\/Values\/3\nAccept: *\/*\nAuthorization: Bearer eyJ0eXAiOi...\nOrigin: https:\/\/us.create.powerapps.com\nX-Ms-Apim-Tokens: ew0KICAidG...\n<\/pre>\n
HTTP\/1.1 200 OK\nContent-Type: application\https://www.microsoft.com/json; charset=utf-8\n\"you entered 3\"\n<\/pre>\n
\nThat is, your web api can collaborate another Azure AD resources like Office 365 API, Azure ARM REST, Power BI REST, etc.<\/p>\nPOST https:\/\/login.microsoftonline.com\/common\/oauth2\/token\nContent-Type: application\/x-www-form-urlencoded\ngrant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion={received access token}&requested_token_use=on_behalf_of&resource={resource id that your api wants to access}&scope=openid&client_id={client id of your web api}&client_secret={client secret of your web api}<\/pre>\n
\nThe sign-in for this custom api, i.e, Azure AD sign-in is needed, when the user launch this app for the first time.\u00a0 (see the following screenshot)<\/p>\n
<\/a><\/p>\nOther Providers (the case of Google)<\/h3>\n
\nTherefore, you register only the custom api proxy as OAuth client into Google Developer Console, get access token for pre-defined Google scopes only (profile, email, etc), and pass this token to your web api. (Or you could use the api key instead.)<\/p>\n
<\/p>\n{\n \"swagger\": \"2.0\",\n \"info\": {\n \"version\": \"v1\",\n \"title\": \"TestApi01\"\n },\n \"host\": \"demo.azurewebsites.net\",\n \"schemes\": [\n \"https\"\n ],\n \"paths\": {\n \"\/api\/Values\/{id}\": {\n \"get\": {\n \"tags\": [\n \"Values\"\n ],\n \"operationId\": \"Values_Get\",\n \"consumes\": [\n ],\n \"produces\": [\n \"application\https://www.microsoft.com/json\",\n \"text\https://www.microsoft.com/json\",\n \"application\/xml\",\n \"text\/xml\"\n ],\n \"parameters\": [\n {\n \"name\": \"id\",\n \"in\": \"path\",\n \"required\": true,\n \"type\": \"integer\",\n \"format\": \"int32\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"OK\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n }\n },\n . . .\n }\n },\n \"definitions\": {\n },\n \"securityDefinitions\": {\n \"oauth2\": {\n \"type\": \"oauth2\",\n \"flow\": \"accessCode\",\n \"authorizationUrl\": \"https:\/\/accounts.google.com\/o\/oauth2\/auth\",\n \"tokenUrl\": \"https:\/\/www.googleapis.com\/oauth2\/v4\/token\",\n \"scopes\": {\n }\n }\n }<\/strong>\n}<\/pre>\n
<\/a>
\n
<\/a><\/p>\n
\nIt is the same like Azure AD, but not. The \u201cAuthorization\u201d header value is the access token for Google scopes, not for your web api.<\/p>\nGET \/api\/Values\/3\nAccept: *\/*\nAuthorization: Bearer ya29.Ci-aAy...\nOrigin: https:\/\/us.create.powerapps.com\nX-Ms-Apim-Tokens: ew0KICAidG...<\/pre>\n
{\n \"token\": {\n \"AccessToken\": \"ya29.Ci-aAy...\",\n \"ExpiresIn\": \"3600\",\n \"IdToken\": \"eyJhbGciOi...\",\n \"RefreshToken\": \"1\/udVjULwb...\",\n \"TokenType\": \"Bearer\",\n \"OAuth2TokenEndPointCredentialLocation\": \"Body\",\n \"ExpiresOn\": \"636150505441694110\",\n \"LoginSettingId\": \"msmanaged-na_customapidemo02.5f989...\",\n \"TokenAcquireTime\": \"11\/18\/2016 6:22:24 AM\"\n },\n \"sku\": \"Enterprise\",\n \"$connectionCreator\": {\n \"objectId\": \"cf258756-2623-47cb-be46-c85d436265bb\",\n \"tenantId\": \"3c839350-a414-442a-9585-8db0b0f5f300\",\n \"userPrincipalName\": \"tsmatsuz@o365directory.onmicrosoft.com\"\n },\n \"$ConnectionKey\": \"Key eyJ0eXAiOi...\",\n \"$callerIdentity\": {\n \"objectid\": \"cf258756-2623-47cb-be46-c85d436265bb\",\n \"prinicipaltype\": \"ActiveDirectory\",\n \"tenantid\": \"3c839350-a414-442a-9585-8db0b0f5f300\",\n \"email\": \"tsmatsuz@o365directory.onmicrosoft.com\"\n }\n}<\/pre>\n