Getting error OWIN start.cs while web API hosting on prem IIS server and api having azure ad bearer authentication - azure-active-directory

I have implemented azure ad authentication in SPA app and validating the token using OWIN start.cs. it is working fine in local environment. below code used for token validation:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = tenant,
TokenValidationParameters = new TokenValidationParameters
{
//ValidAudiences = new[] { Audience },
ValidAudience = validateAudience,
ValidateIssuer = false,
ValidIssuers = new[] { ValidIssuers }
}
});
when I deployed this published code on prem server and run web api it throws error as mentioned in below screen shot. I have used Microsoft.Owin.Security.ActiveDirectory version 4.2.2.0,
can anyone help on this ?

Basically, the error task was canceled is expected when an HTTP request is canceled maybe if the user closes the page suddenly. or cancels before execution completes.
The TaskCanceledException is mostly timeout.But to check the exception, it may have to be inspected with try catch.
try
{
var response = task.Result;
}
catch (TaskCanceledException ex)
{
// Check ex.CancellationToken.IsCancellationRequested here.
// If false, we may assume it was a timeout in most cases.
}
you can try to suppress response if the cancellation token occurred by using if (cancellationToken.IsCancellationRequested)
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
if (cancellationToken.IsCancellationRequested)
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
return response;
If it is due to time out ,it can be set to some value.Plesae check the references.
var clientHttp = new HttpClient();
httpClient.Timeout = TimeSpan.FromMinutes(30)
In some cases of use , await can be used for simultaneous tasks to be completed with async.
References:
c# - "Task was canceled" errors on Azure website - Stack Overflow
c# - HttpClient - A task was cancelled? - Stack Overflow

Related

How to implement Single Sign On in ASP.NET MVC application

We have developed 2 applications in ASP.NET MVC. We have used ASP.NET Identity in both applications for user authentication. Both applications use the same database. Also both apps are hosted on Azure Portal.
We would like to implement SSO in both applications, so when I log in to one application, the second application doesn't ask for login again and authenticates the already logged in user.
We have implemented to share authentication cookies among ASP.NET apps as per the Microsoft document (open the link shared below), but it's not working. I have posted code below.
https://learn.microsoft.com/en-us/aspnet/core/security/cookie-sharing?view=aspnetcore-2.1#sharing-authentication-cookies-between-aspnet-4x-and-aspnet-core-applications
I have written this code in Startup.Auth.cs:
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
CookieName = ".AspNet.SharedCookie",
CookieDomain= ".azurewebsites.net",
SlidingExpiration = true,
ExpireTimeSpan = TimeSpan.FromMinutes(120),
LoginPath = PathString.FromUriComponent("/Account/Login"),
LogoutPath = PathString.FromUriComponent("/Account/Logout"),
TicketDataFormat = new AspNetTicketDataFormat(
new DataProtectorShim(
DataProtectionProvider.Create(new DirectoryInfo("C:\\ApplicationData"),
(builder) =>
{
builder.SetApplicationName("SharedCookieApp");
})
.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies." +
"CookieAuthenticationMiddleware",
"Cookies.Application",
"v2"))),
CookieManager = new ChunkingCookieManager()
});
}
Also added claim when user logged in successfully in login method as below.
var user1 = await UserManager.FindByNameAsync(model.Email);
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.NameIdentifier, user1.Id));
claims.Add(new Claim(ClaimTypes.Name, model.Email));
var id = new ClaimsIdentity(claims,DefaultAuthenticationTypes.ApplicationCookie);
var ctx = Request.GetOwinContext();
var authenticationManager = ctx.Authentication;
authenticationManager.SignIn(new AuthenticationProperties()
{
AllowRefresh = true,
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddMinutes(30),
IssuedUtc = DateTime.UtcNow
}, id);
This works fine in localhost but when it is published in Azure portal, it doesn't work. It seems that the authentication cookie is not shared among the 2 apps on Azure Portal because Azure doesn't allow to access directory location hence it gives error like 'Access Denied' and I don't know how to use Azure Key vault or database to store cookie.
Can you please guide me if I have missed something or have did incorrectly. Your earlier response would be highly appreciated. Let me know if you need any other details.
Regards,
Kiran Shah

How to trigger an session expired popup after ten minutes using #msal - react and azure ad

Auth Provider : Azure Active Directory
Client library : #azure/msal-react
As explained here my msal token expires after one hour MSAL token expires after 1 hour, My requirement is I would like to configure a session time of 15 minutes ( or 10 minutes) after which I wanna trigger a popup, saying please login again? Is there a way to do using msal-react.
Currently, after one hour am calling acquireTokenSilent to acquire the new token, using which client is unaware that this happened and client thinks it has infinite lifetime for the session.
Here is the implementation
export const refreshIdToken = async (msalInstance: IPublicClientApplication) => {
const account = msalInstance.getActiveAccount();
try {
if (account != null) {
const token = await msalInstance.acquireTokenSilent({
scopes: loginRequest.scopes,
account
});
return token.idToken;
}
} catch (error) {
if (error instanceof InteractionRequiredAuthError) {
return msalInstance.acquireTokenRedirect(loginRequest);
} else {
console.error(error);
}
}
};
const token = await refreshIdToken(msalInstance);// This will never expires , as it always refresh after one hour internally
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
//api call
What are the steps I need to configure from Azure AD end or client code end?
Thanks in advance.
You can specify the lifetime of token of access, ID or SAML token issued by the Microsoft identity platform. You can set the lifetime of token for specific service principle in your organization. However, Microsoft does not currently support configuration token lifetime of Manage identity service principle.
Note: Configuration token lifetime policy only applies to mobile and desktop clients that access SharePoint online and OneDrive for business resources but id does not apply to web browser sessions.
For the new update of 2021, you cannot configure the refresh token and session token lifetime. New tokens issues after existing tokens have expired are now to set to the default configuration.

Error: AWS Web RTC Verification with Cognito

I am trying to connect my javascript app AWS WebRTC with a Cognito user to get its credentials dynamically but faced the following error code:
json.js:52 Uncaught (in promise) CredentialsError: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
I have done hard coding my credentials into the configuration and it has work successfully, however that's a bad practice hence I am trying to get AWS Web RTC credentials via my Cognito user. I have setup user pool and link in to my federal identities already. The credentials are now managed by AWS Amplify which loads AWS user profile from config file (./aws/credentials).
Following this two guides:
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-integrating-user-pools-with-identity-pools.html
https://docs.aws.amazon.com/cognito/latest/developerguide/getting-credentials.html
I've written the following snippet to get my credentials but now faced the error.
AWS.config.region = '<REGION>';
AWS.config.update({
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: '<Region>:<IdentitiyPoolID>',
Logins: {
'cognito-idp.<Region>.amazonaws.com/<UserPoolID> ': <id token from cognito>,
},
}),
});
var accessKeyId;
var secretAccessKey;
AWS.config.credentials.get(function () {
accessKeyId = AWS.config.credentials.accessKeyId;
secretAccessKey = AWS.config.credentials.secretAccessKey;
});
const state = {
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey,
region: 'region',
}
async function startPlayerForViewer();
Any helps is much appreciated ! Cant find much updated resources/examples online.
credentials.get() is an async operation that receives the keys in a callback, while the state definition happens before that callback is received. Hence, the keys are not set. You need to ensure that you define the state after the callback and ensure that the connection happens afterwards.

Office 365 Access via Graph API

I have a problem (or two) with regards to accessing my office 365 account via the Microsoft Graph API.
The first issue is that I have a java program that is attempting to list all users in the office 365 subscription. I am calling https://graph.microsoft.com/v1.0/users/ but getting a 403 forbidden back.
On the App registration, I have added permissions including User.Read, User.ReadBasic.All, User.ReadWrite on both delegated and app permissions.
I have also tried to use the Graph Explorer, but when I enter to use my account it still uses the built in graph user and doesn't show my application login info. Not sure if these are related.
Here is code snippet that results in a 403
AuthenticationResult result = getAccessTokenFromUserCredentials(RESOURCE_GRAPH, ID, PASSWORD);
URL url = new URL("https://graph.microsoft.com/v1.0/users/") ;
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Authorization", "Bearer "+result.getAccessToken());
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
And here is the method that gets the token
private static AuthenticationResult getAccessTokenFromUserCredentials(String resource,
String username, String password) throws Exception {
AuthenticationContext context;
AuthenticationResult result = null;
ExecutorService service = null;
try {
service = Executors.newFixedThreadPool(1);
context = new AuthenticationContext(AUTHORITY, false, service);
Future<AuthenticationResult> future = context.acquireToken(
resource, CLIENT_ID, username, password,
null);
result = future.get();
} finally {
service.shutdown();
}
if (result == null) {
throw new ServiceUnavailableException(
"authentication result was null");
}
return result;
}
The app register in apps.dev.microsoft.com works with the v2.0 endpoint .Please click here for more details about the v2.0 endpoint .
You can acquiring token using v2.0 authentication protocols and Azure Active Directory v2.0 authentication libraries . During authentication , you need to do user consent or admin consent for User.ReadBasic.All permission . After consenting , access token includes that delegate permission and will work when calling list users operation .
OK, thought I should post up the answer. Firstly, and most confusingly, the apps.dev.microsoft.com registration didn't seem to work (even though I was using the V2.0 endpoint and the version 2 libraries).
However, when I registered the app using the azure portal directly, this fixed the issue. I have subsequently been able to access the service correctly.
It seems strange that, although the authentication / authorisation service was standard for my app and worked perfectly for accessing Sharepoint / One Drive etc, but, when wanting to hit the users endpoint, it would only work if it was registered in the portal.azure.com.
Many thanks everyone for your help.

OpenIdConnectAuthenticationNotifications.AuthorizationCodeReceived event not firing

using this sample:
https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect
This works as expected when running it locally
But when we deploy it (azure web app), it still authenticates, but the OpenIdConnectAuthenticationNotifications.AuthorizationCodeReceived event is not firing.
This the code.
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = Authority,
PostLogoutRedirectUri = redirectUri,
RedirectUri = redirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed
}
});
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
var code = context.Code;
ClientCredential credential = new ClientCredential(clientId, appKey);
string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));
Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, credential, graphResourceId);
}
This is a problem because it requires caching of the token to make an outbound call.
Since it doesn’t have it, it throws.
There was an issue that caused this related to a trailing slash after the redir url but we’ve already tried that.
So two questions…
1) Under what conditions would event get fired and why would this work when running locally? According to the docs it should be "Invoked after security token validation if an authorization code is present in the protocol message."
2) What is the best way to debug this? Not clear on what to look for here.
1) Under what conditions would event get fired and why would this work when running locally? According to the docs it should be "Invoked after security token validation if an authorization code is present in the protocol message."
As the document point, this event will fire when the web app verify the authorization code is present in the protocol message.
2) What is the best way to debug this? Not clear on what to look for here.
There are many reason may cause the exception when you call the request with the access_token. For example, based on the code you were using the NaiveSessionCache which persist the token using the Sesstion object. It means that you may also get the exception when you deploy the web app with multiple instance. To trouble shoot this issue, I suggest that you remote debug the project to find the root cause. For remote debug, you can refer the document below:
Introduction to Remote Debugging on Azure Web Sites

Resources