how to get Azure Active Directory B2C working with Bot Framework? - azure

so far I've not been able to get this working with the bot framework. I spent all day but only managed to get .net api example (https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) working with AD B2C. I'm not sure where it grabs the bearer token that I want to pass to BotUserData...
I've tried following https://azure.microsoft.com/en-us/blog/bot-framework-made-better-with-azure/
but in reality the solution does not build successfully and I've resorted to just taking code from there and into my bot framework sample template....however, when it asks me to login through MS and I do, I am not able to proceed and it doesn't seem like that blog is using the AD B2C policies.
so how do you integrate AD B2C with Bot Framework? Is it possible to call /Account/SignIn URL from bot framework to authenticate the user? Afterwards, how would you capture the token and pass it to BotUserData?

You might want to take a look to the Facebook Auth sample to get an idea of a potential flow for the Auth scenario. For Azure AD, you need to do a similar flow.
Let's say your user send a "Login" message to your bot. The bot should respond with an auth URL and ask the user to login to the service using that URL. You can use the GetAuthorizationRequestURL method of ADAL for that.
Then you will have a Web API which will basically expose an endpoint that will be the reply URL of Azure AD. Once the users completes the login, a message will be posted to your Web API where you will be able to get the authorization code and perform the calls to get the Access Token. After that, you can just do the same they are doing in the Facebook Sample Web API which involves resuming the conversation with the Bot, sending a message with the access token (so it can be persisted in the PerUserInConversationData bag (check this line of code).
After that you have the access token available to perform any call that requires an access token.
Update
There are two new samples that you might want to take a look since they are implementing the workflow being discussed.
GraphBot from the BotBuilder repo.
AuthBot from Mat Velloso
Hope this helps.

Follow this tutorial for Bot side code development, i focus on configuration at B2C and Azure level here:
OAuth Connection
Client id
This is taken from the Application ID field in your B2C app's properties. It's the equivalent of a Microsoft app ID taken from any other AAD app registration.
Client secret
This is generated using the steps in this tutorial.
Select Keys and then click Generate key.
Select Save to view the key. Make note of the App key value. You use the value as the application secret in your application's code.
Use AAD V2 configuration in oAuth settings in bot channel registration - new oauth connection settings.
Fill the above details by following the steps and values we got from them.
Authorization/Token/Refresh URL
I followed on this one with
https://login.microsoftonline.com/tfp///oauth2/v2.0/authorize
for the Authorization URL and
https://login.microsoftonline.com/tfp///oauth2/v2.0/token
for the Token and Refresh URL's.
For I used the URL format (kyleorg.onmicrosoft.com) rather than the GUID format, but using the GUID also seems to work.
is the name of a user flow, like B2C_1_userflow. I created one with this tutorial.
Scopes
Using the scopes openid offline_access I am able to sign in successfully, but to my astonishment the token returned is empty.
Then I found this document which suggests using the client ID itself as a scope.
When I reuse the value from the Client id field in my Scopes field, a token is returned successfully and my bot is able to use the connection.
You can combine this with other scopes as needed, but for the sake of experimentation I highly recommend getting the simplest implementation to work first.
Let me know if these instructions work, and if they don't then we'll see if the difference lies in how we've set up our B2C apps.
As a bonus, I should mention that after you get a token you can paste it into https://jwt.ms/ to decode it and see if it recognized your B2C user correctly. Always refresh the page when pasting a new token to make sure it doesn't keep showing you the information from the last token.
Referred this document.

Related

Obtain SharePoint specific access token for a non-user application

I am working on a PHP web app that needs to make HTTP requests to the Sharepoint API with Sites.Selected permission to a specific SharePoint site. It is NOT viable for me to provide a user sign-in experience so I need to treat it as a non-user/daemon application.
I've read the docs and looked at many different forums for the solution but as of yet I've been unsuccessfull in obtaining a SPO specific access token, although I think I'm close.
I am using this StackOverflow answer as a guide: https://stackoverflow.com/a/63386756/19038862
This is what I've done:
Registered an Azure App: (Image of my Azure App Overview)
Created a client secret in the App dashboard: (Image of the client secret page)
Successfully sent a request to https://login.microsoftonline.com/{{app_tenant_id}}/oauth2/v2.0/token using the client secret in Postman: (Image of Postman request)
The request made in step 3 returns an access token (I assume a MS Graph access token?), but it DOES NOT return a refresh token, which is what the afforementioned StackOverflow answer suggests you need to "swap" for an SPO specific access token.
How do I obtain this refresh token so that I can swap it for a SPO access token? Or what better way is there to get my hands on a SPO specific access token from a non-user app?
I wrote this gist to guide you into getting Sites.Selected access to the desired site:
https://gist.github.com/ruanswanepoel/14fd1c97972cabf9ca3d6c0d9c5fc542
This guide shows you how to configure this as Application permissions, and via the Graph API.
I've found going through the Graph API is the best way to go.
Also strangely it's not possible to get delegated Sites.Selected permissions. You must set it up as an Application permission.
In the guide is described that you have to get a delegated auth token from graph but you are getting an application auth token. The token response of this flow does not contain a refresh_token. See here.
But you already wrote that you are not able to provide a user sign-in experience. One workaround would be to once manually get the access_token and refresh_token of a user with the delegated flow and then periodically get a new access_token with the refresh_token on your server. You could store these values in your database and update them when you fetch a new one.
First, the daemon-based client credential flow does not return a refresh token for you. You also can't redeem the refresh token of the graph API for an access token for SPO, which are two completely different API resources.
To get an access token for SPO you just need to set scope to: https://{tenant-name}.sharepoint.com/.default.

How I can change password in Azure AD

I am using Microsoft azure ad a authentication. When I am trying to change the user password with graph api it will give me an error
I have also set permission that is required for password change, but then it will also not work
I have wrote code in node.js with like this
const changePassword = {
currentPassword: ctx.request.body.currentPassword,
newPassword: ctx.request.body.newPassword
};
const client = createAuthenticated.createAuthenticatedClient();
await client.api('/me/changePassword').post(changePassword);
The changing password api can only support delegate permission, it has been indicated in api document, and it also appeared in your error message.
Delegate api permission means you can't use client credential flow to generate access token/credential to call this api, you can only use such as ropc flow or auth code flow to generate the access token.
I think you've read this sample to call the api, but you didn't choose a correct authentication provider. If your app is a website which required user to sign in, then you may choose this one. But pls note, the client-credential-flow is not suitable for this scenario.
=======================Update====================
The html+js code in my this answer provides a sample which integrate msal to let user sign in and generate access token for calling graph api.
Change AzureMgmtScops value to scopes:["Directory.AccessAsUser.All"] then it will return you an access token with this permission, then pls use this token to send a post request like this, I think you can then finish your task. But this way will not change your server side, it's suitable for the structure which is frontend-backend separated.

Microsoft Graph API: how to get access token without browser

I would like to upload a given file to Sharepoint. I'm using the Microsoft Graph API.
The documentation follows this workflow:
1. If no token, redirect the user to the Microsoft signin page.
2. The user is then redirected to the application, with an access token
3. Use access token to have an authorization bearer
4. Do what you gotta do...
My problem is the sign-in part. I don't want my users to be redirected to the Microsoft signin page. I want my application to connect and get the access token in the background (with cURL or whatever).
How can I do that? Why is the "open in browser" necessary?
I tried to replicate the sign-in process, but all I get back is the HTML response from the signin page.
Thanks in advance.
Your application act as a single-tenant service or daemon app.
The documentation about this scenario is here : https://developer.microsoft.com/en-us/graph/docs/authorization/app_only
The application must be registered in the AzureAD directory corresponding to the Office365 tenant
A first request is made by passing the application unique identifier and secret key as registered in the directory. This request returns an access token
The access token can now be used in the Authorization header of the following request to the Microsoft Graph API.
This method (of using Client ID and Secret) works well but there are other ways which may be better suited for similar scenarios.
The one major thing which is missing in access token generated this way is a user, meaning the token only contains the identity of the OAuth application (client) which called it but is not associated with any user for the request.
This could have a couple of implications:
Since the token is not associated with a specific user you will not know who performed the operation. In your example, you would not know who uploaded the file (and other similar information may be missing).
Access token without users will not work at all for some methods. For those, you need a delegated token.
Creating a delegated token requires some effort, if you are interested you can find the details in my article:
Getting Access Token for Microsoft Graph Using OAuth REST API

Why is MSDN telling me to create a OAuth2.0 client when I just want a barebone test for my API?

I have a REST API, written with express directly. Nowhere in it do I use session, and authentification is for now done using JWT.
However, I dislike having to handle, save and secure user's credentials, that is when I heard about Azure Active Directory.
Adding passport to my app was easy enought, but that's when trouble started.
First, I had to search what strategy I needed, and all of them seems to require the server to maintain sessions/remember who is logged in, all the while using JWT internally. That seems contradictory, JWT is supposed to remove the need of maintaining session.
Finally, I found this MS example which use the Bearer strategy without session.
After setting it up (changing the config file for the right tenant, client ID, changing the routes for a test app more representative of my API), I tried to use them. The protection work well since I am indeed "Unauthorized". But how do I get a valid token to send?
The MSDN guide that use that quickstart don't mention it at all, just redirecting to the AAD library for Android or iOS, implicitely telling me to develop a test app in another language when I just want a crude tool to test if my test server work at all!
That is especially frustrating since I am pretty sure it is "just" a series of HTTP(S) request on the tenant, and the call to the api with the token attached, but I can't find anything to do just that.
/!\: I know asking for something as vague as "How can I do that" isn't a good question, and this question isn't one. What I am asking is why I couldn't find some tools like POSTMan that implement OAuth and allow to quickly test and debug a OAuth protected API. What are the reason that push MSDN to tell me to write a custom tool myself instead of providing a barebone one?
The code sample you mentioned in the post is using the Azure AD V2.0 endpoint. We can use OAuth 2.0 code grant and client credentials flows to acquire the token from this endpoint.
To compose the OAuth 2.0 request directly you can refer the links below:
v2.0 Protocols - OAuth 2.0 Authorization Code Flow
Azure Active Directory v2.0 and the OAuth 2.0 client credentials flow
In addition, the access tokens issued by the v2.0 endpoint can be consumed only by Microsoft Services. Your apps shouldn't need to perform any validation or inspection of access tokens for any of the currently supported scenarios. You can treat access tokens as completely opaque. They are just strings that your app can pass to Microsoft in HTTP requests(refer here).
If you want to protect the custom web API with Azure AD, you can use the Azure AD v1.0 endpoint.
For getting a valid token to send to your API, you'll need to do an auth request to login.microsoftonline.com and get an access token (in the JWT format). Then you can send this token to your api in the http body: "Bearer ey...".
If you want a full sample with a client app that hits that API sample you tried:
Dashboard w/ all the samples for Azure AD Converged Apps
Simple Windows Desktop App
Angular SPA
Node Web API

OAuth authentication and consumer secrets

I have a webservice which acts as backend for smartphone apps.
I want to be able to authenticate users as painless as possible, but even though I thought I understood the OAuth I must admit there are some missing pieces here and there.
Authentication:
Let's say the user has an Android phone. He is probably already Authenticated to Google and it would be really nice if I could just extend this authentication to my webservice. Android has OAuth support so the users opens his app, grants permissions to use his google account and the app authenticates him to the web service.
Web service
Since the service should accept users from all kinds of devices it should not be Google specific. It should be possible to register an account and login from any device. I'm unsure if it is possible to register a new account with OAuth alone or if you need some other kind of authentication first - OpenID for instance.
How would the flow be for the generic webservice? A generic API for registering a user and granting him access to an API?
Furthermore - I do not want to control the devices connecting to this service. I can see OAuth requires a consumer_key and a consumer_secret. If I run everything through SSL - is the consumer secret still secret or can I just use some dummy values? Thus avoiding creating a device-registration system where people can acquire a consumer_secret?
For your case, if you want to use Google/Facebook etc as authentication providers, you will need to use the 'Authorization Code' flow of Oauth2. In this case, you register with Google/FB as a developer and get a client id and secret for using their API.
Then you obtain the Login with Google/Facebook button and code, which you will use to fire a "webview" or an embedded browser where the user will be taken to google/facebook and asked to provide his login credentials.
Upon success, an authorization code will be sent to a redirect url that you would have provided while registering as a developer at Google/Facebook. You will need to catch this authorization code and then again call the relevant API to obtain the access token, which you can then use to fetch the user's details to register him in case of first time or authenticate him if he's already registered through this method earlier.

Resources