Authentication to Sharepoint Online with CSOM more than one Context - csom

In my desktop application based on .NET Framework 4.8, I have to change the context to another site.
When I call it the first time it works perfect, but the another time I get an empty Login window and it stops at GetWebLoginClientContext()
var authManager = new OfficeDevPnP.Core.AuthenticationManager();
context = authManager.GetWebLoginClientContext(siteUrl);
Web web = context.Web;
context.Load(web, w => w.Title);
context.ExecuteQuery();

Related

How I can call an api from MVC .net 4.7.2 using Microsoft Identity Planform (Azure AD

I am following a tutorial from microsoft docs and I have created an api with Microsoft Identity Platform using Azure AD in asp.net core 5.
The tutorialI followed shows how to call an api from asp.net core 5, and I have done that part but now I want to call the api from asp.net 4.7.2. Since I am new to apis and example I am finding are not using Microsoft Identity platform to call an api secured by microsoft identity
Can someone point me to document, tutorial, or code which shows me how I can call the api. Code should be written in asp.net not core.
I have done some part but stuck on calling the api.
See the below code
Api methods:
I have already setup the api and web app in Azure portal and configured permission to 2 of the scope.
Method in api.
GetCategory()
GetCatalog()
private async Task OnAuthorizationCodeReceivedAsync(AuthorizationCodeReceivedNotification
notification)
{
notification.HandleCodeRedemption();
var idClient = ConfidentialClientApplicationBuilder.Create(clientId)
.WithRedirectUri(redirectUri)
.WithClientSecret(clientSecret)
.WithAuthority(authority)
.Build();
var signedInUser = new ClaimsPrincipal(notification.AuthenticationTicket.Identity);
try
{
var apiScope = "catalog.Read, Category.Read";
string[] scopes = apiScope.Split(' ');
var result = await idClient.AcquireTokenByAuthorizationCode(
scopes, notification.Code).ExecuteAsync();
//rest of the code to call the api for both scope
// and if i have to do add some code to controller
Not sure if you are still looking for an answer but here it goes.
Once you get the accessToken with required scope, you just need to add it as Authorization Header when you make a call to the API:
const string Scheme = "Bearer";
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(Scheme, result.AccessToken);
var result = await httpClient.SendAsync(httpRequestMessage)

How To Add Custom Parameters to Identity Server LogoutRequest?

I have a legacy ASP.NET MVC (Owin) website using the latest OpenIdConnect library, and .NET Core 3.1 MVC Identity Server app running the latest Identity Server package.
I need to pass a custom parameter to Identity Server at logout (the use case is that I need to display a different "logout reason" message depending on how the logout was initiated on the client). So I'm intercepting the OpenIdRequestType.Logout notification setting a custom parameter via n.ProtocolMessage.SetParameter("some_key", "SomeValue") and I can see that the Parameters dictionary has the new value in it. But when the Logout post to my Identity Server comes in, the LogoutRequest.Parameters collection is empty.
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = async n =>
{
switch (n.ProtocolMessage.RequestType)
{
case OpenIdConnectRequestType.Logout:
n.ProtocolMessage.SetParameter("some_key", "SomeValue");
break;
...
On the Identity Server side, I'm calling
var logout = await _interaction.GetLogoutContextAsync(logoutId);
and finding that logout.Parameters is empty.
I found this SO question that suggests that the oidc-client javascript library can handle adding additional parameters that will show up in the LogoutRequest object so I'm guessing it's possible and I'm just missing something simple. Any ideas would be appreciated.

User.Identity.Name is different before and after publishing to Azure

I am using #User.Identity.Name in my Asp.net mvc web application. This is shown as Domain\user on local and user#domain.com on azure site once deployed. Instead of using #User.Identity.Name, is there any way to make it unique on local and server. I have many code breaking areas due to this conflict.
I added Azure active directory authentication to my application which is hosted on Azure.
using (var context = new PrincipalContext(ContextType.Domain))
{
var principal = UserPrincipal.FindByIdentity(context, User.Identity.Name);
var displayName = principal?.DisplayName;
}
this displayName is shown on local and once published to Azure it is like null "". What would be the best way to show display name on Azure server once published?
It seems you are using the AD libraries for traditional on-premise AD. To program against Azure AD , you could use OpenID Connect to authenticate users from an Azure AD tenant. Please see the code sample below :
https://github.com/Azure-Samples/active-directory-dotnet-webapp-openidconnect
To get the display name of the current user , you could try :
var displayName = ((System.Security.Claims.ClaimsIdentity)User.Identity).Claims.Where(c => c.Type == "name").FirstOrDefault().Value;
If you also want to show Domain\DisplayName when using Azure AD , you could get domain name by :
var domian= ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value.Split('#')[1].ToString();

System.Threading.ThreadStateException in ASP.NET MVC 5 when Acquire Token from WAAD

I'm implementing the following scenario: ASP.NET MVC 5 application access OData WebAPI with Azure Active Directory authentication (like in this article: http://msdn.microsoft.com/en-us/magazine/dn463788.aspx ).
However, when I call AuthenticationContext.AcquireToken I get System.Threading.ThreadStateException saying: ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded
apartment.
EDITED:
Steps to reproduce:
Create New MVC project with Organizational Authentication. Use your Windows Azure Domain and MSDN Account
Add Actice Directory Authentication Library via NuGet
Add action with the following code:
public async Task<ActionResult> Index(){
AuthenticationContext ac = new AuthenticationContext("https://login.windows.net/domain.onmicrosoft.com");
AuthenticationResult ar = ac.AcquireToken("https://domain.onmicrosoft.com/WindowsAzureADWebAPITest",
"a4836f83-0f69-48ed-aa2b-88d0aed69652",
new Uri("https://domain.onmicrosoft.com/myWebAPItestclient")
);
// Call Web API
string authHeader = ar.CreateAuthorizationHeader();
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://server.com:44353/api/Values");
request.Headers.TryAddWithoutValidation("Authorization", authHeader);
HttpResponseMessage response = await client.SendAsync(request);
string responseString = await response.Content.ReadAsStringAsync();
return View();
}
Run the code and reproduce the issue (AcqureToken method call).
Please suggest a fix.
Thank you!
That particular overload of AcquireToken() is only usable in a native client app because the way it handles user authentication is by opening a browser window to login.windows.net. This requires the app to host a browser ActiveX control and that's why it needs an STA thread.
Now, in your example the code runs inside IIS on the server machine where hosting ActiveX controls is just not possible.
What you really need is delegation which is described here: http://www.cloudidentity.com/blog/2013/10/29/using-adals-acquiretokenby-authorizationcode-to-call-a-web-api-from-a-web-app/
Same author, just the different article.

How to print from MVC3 controller from server

Code below is used to print from ASP .NET MVC3 application to Samsung ML-331x Series printer connected to IP address in LAN and shared in server as Samsung ML-331x Series
Nothing is printed. Execution stops at doc.Print() line.
Every controller call adds new unfinished job:
Those jobs are never finished, only iisreset clears them.
Server is Windows 2003 + IIS
It worked in MVC2 .NET 3.5 application. ForteSSL VPN was installed in server and application was upgraded to
MVC3 and .NET 4.
(After that printing was not checked immediately, so I'm not sure is this related to those changes).
User NETWORK SERVICE with all permissions is added to printer users but problem persists.
Running application in development computer by pressing F5 in visual studio with Web Developer server and calling with controller to print to PDF Creator works OK.
How to print from controller in server ?
public ActionResult PrintTest()
{
var doc = new PrintDocument();
doc.PrinterSettings.PrinterName = "Samsung ML-331x Series";
doc.PrintPage += new PrintPageEventHandler(TestProvideContent);
doc.Print();
return new ContentResult()
{
Content = "Printed"
};
}
public void TestProvideContent(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawString("Test",
new Font("Arial", 12),
Brushes.Black,
e.MarginBounds.Left,
e.MarginBounds.Top);
}
Update
Application runs at full trust Level.
Application log in event viewer does not have any entries about this.
Using Programmatically "hello world" default SERVER-side printer in ASP.NET MVC I tried to use printer name with server name as \\SERVER\Samsung ML-331x Series but problem persists.

Resources