Obtaining authorization token from Azure AD with Dotnetopenauth - azure

I am trying to obtain authorization token from Azure AD through DotNetOpenAuth library. I do not want to use ADAL because I have a huge project in .net 3.5 and ADAL does not supports .net 3.5 (only .net > 4). However, I can't quite get it to work with Azure AD. I do not know what to configure. So far, this is what I have:
private static WebServerClient _webServerClient;
private static string _accessToken;
// Client ID (as obtained from Azure AD portal)
private static string clientId = "here goes my client id guid";
// Client Secret (as obtained from Azure AD portal)
private static string appKey = "here goes my secret";
private static string aadInstance = "https://login.microsoftonline.com/{0}";
private static string tenant = "mytenant.domain.com";
private static string authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
// Azure AD resource I am trying to access
private static string serviceResourceId = "https://mytenant.domain.com/protectedresource";
private static void InitializeWebServerClient()
{
var authorizationServer = new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri(""/* WHAT TO PUT HERE */),
TokenEndpoint = new Uri(""/* WHAT TO PUT HERE */)
};
_webServerClient = new WebServerClient(authorizationServer, clientId, appKey);
}
private static void RequestToken()
{
var state = _webServerClient.GetClientAccessToken();
_accessToken = state.AccessToken;
}
static void Main(string[] args) {
InitializeWebServerClient();
RequestToken();
}
The problem is I do not know what to place here. I do not know what values I should place here:
AuthorizationEndpoint = new Uri(""/* WHAT TO PUT HERE */),
TokenEndpoint = new Uri(""/* WHAT TO PUT HERE */)

Check if this GitHub sample assists you with authentication. It has 3 methods for authenticating and acquiring authentication token with detailed instructions. Check the app.config for sample values and method comments for details on what is required.
Link to the sample: Azure Authentication GitHub Sample
Related blog for the sample: Azure Authentication - Authenticating any Azure API Request in your Application

I believe the two endpoints you want are:
https://login.windows.net/{{tenantId}}/oauth2/authorize
https://login.windows.net/{tenantId}/oauth2/token
Where {tenantId} is your tenant's GUID identifier. It may also work with your domain as well, but I haven't checked that.

Related

Usage of the /common endpoint is not supported for such applications created after '10/15/2018' issue

Similar issue here. I have checked the answer and try to implement all the possible forms of link in my startup.cs class with the following code:
var idClient = ConfidentialClientApplicationBuilder.Create(appId)
.WithRedirectUri(redirectUri)
.WithTenantId(tenantId)
.WithClientSecret(appSecret)
.WithAuthority(Authority) // Authority contains the link as mentioned in the page(link attached above)
.Build();
I still get the similar error:
"OpenIdConnectMessage.Error was not null, indicating an error. Error: 'invalid_request'. Error_Description (may be empty): 'AADSTS50194: Application 'xxx-xxx-xxx-xxx-xxxx'(ASPNET-Quickstart) is not configured as a multi-tenant application. Usage of the /common endpoint is not supported for such applications created after '10/15/2018'. Use a tenant-specific endpoint or configure the application to be multi-tenant.
Trace ID: xxx-xxx-xxx-xxx-xxxx
Correlation ID: xxx-xxx-xxx-xxx-xxxx
Timestamp: 2022-06-11 05:33:24Z'. Error_Uri (may be empty): 'error_uri is null'."
The combination of links I have used in variable Authority are the following: "https://login.microsoftonline.com/MY_TENANT_NAME" and "https://login.microsoftonline.com/MY_TENANT_ID"
I am being redirect to login page but after entering credentials OnAuthenticationFailedAsync method is being executed. This is the code of my startup class:
[assembly: OwinStartup(typeof(Web.Startup))]
namespace Web
{
public partial class Startup
{
// Load configuration settings from PrivateSettings.config
private static string appId = ConfigurationManager.AppSettings["ida:AppId"];
private static string appSecret = ConfigurationManager.AppSettings["ida:AppSecret"];
private static string redirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
private static string graphScopes = ConfigurationManager.AppSettings["ida:AppScopes"];
private static string tenantId = ConfigurationManager.AppSettings["ida:tenantId"];
private static string aadInstance = EnsureTrailingSlash(ConfigurationManager.AppSettings["ida:AADInstance"]);
public static string Authority = "https://graph.microsoft.com/"+ tenantId;
string graphResourceId = "https://graph.microsoft.com/";
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = appId,
Authority = "https://login.microsoftonline.com/common/v2.0",
Scope = $"openid email profile offline_access {graphScopes}",
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
TokenValidationParameters = new TokenValidationParameters
{
// For demo purposes only, see below
ValidateIssuer = true
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailedAsync,
AuthorizationCodeReceived = OnAuthorizationCodeReceivedAsync
}
}
);
}
private static Task OnAuthenticationFailedAsync(AuthenticationFailedNotification<OpenIdConnectMessage,
OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
string redirect = $"/Home/Error?message={notification.Exception.Message}";
if (notification.ProtocolMessage != null && !string.IsNullOrEmpty(notification.ProtocolMessage.ErrorDescription))
{
redirect += $"&debug={notification.ProtocolMessage.ErrorDescription}";
}
notification.Response.Redirect(redirect);
return Task.FromResult(0);
}
private async Task OnAuthorizationCodeReceivedAsync(AuthorizationCodeReceivedNotification notification)
{
var idClient = ConfidentialClientApplicationBuilder.Create(appId)
.WithRedirectUri(redirectUri)
.WithTenantId(tenantId)
.WithClientSecret(appSecret)
.WithAuthority(Authority)
.Build();
string email = string.Empty;
try
{
string[] scopes = graphScopes.Split(' ');
var result = await idClient.AcquireTokenByAuthorizationCode(
scopes, notification.Code).ExecuteAsync();
email = await GraphHelper.GetUserDetailsAsync(result.AccessToken);
}
catch (MsalException ex)
{
System.Diagnostics.Trace.TraceError(ex.Message);
}
notification.HandleResponse();
notification.Response.Redirect($"/Account/SignInAzure?email={email}");
}
private static string EnsureTrailingSlash(string value)
{
if (value == null)
{
value = string.Empty;
}
if (!value.EndsWith("/", StringComparison.Ordinal))
{
return value + "/";
}
return value;
}
}
}
My application is for single tenant so please don't suggest me to change the setting and make it for multi-tenant.
Please check below points:
After trying to change it to specific tenant i.e.;
After changing to Ex: - https://login.microsoftonline.com/contoso.onmicrosoft.com (or tenant id),
please save changes ,refresh portal / everything and try again.
If still it shows the error , check if the Application is registered to the Azure AD Tenant as Multi Tenant Application.
Then if it still remains check if the account is actually on Azure
AD ,as this error can occur when the user credentials you are trying
to use does not belong to the same tenant where the application is
actually registered in.
If it is different tenant and you are trying to access from different
account, then you may need to change its supported account types to
any organizational directory or you need to check for correct
credentials. If not check everything or create a new app registration
.
Also please check this "Use a tenant-specific endpoint or configure the application to be multi-tenant" when signing into my Azure website for possible
ways to solve the issue.
Else you can raise a support request
References:
msal - MsalException: Applicationis not configured as a multi-tenant
application. Android - Stack Overflow
Use single-tenant Azure AD apps with Microsoft Graph Toolkit -
Waldek Mastykarz

PowerBi Embedded suspend and resume capacity using .NET SDK

I'm trying to figure out whether there is a azure management NuGet package that I can use to communicate with this part of the API for suspending and resuming my powerbi embedded capacities.
I have been unable to find it. Does what I'm looking for exist?
Does what I'm looking for exist?
In short, No. As the link you provided, it need azure_auth to access to Power BI Embedded.
You could use the below code to get the access_token and call the rest api you provide.
private static string redirectUri = "https://login.live.com/oauth20_desktop.srf";
private static string resourceUri = "https://analysis.windows.net/powerbi/api";
private static string authorityUri = "https://login.windows.net/common/oauth2/authorize";
// Obtain at https://dev.powerbi.com/apps
private static string clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
private static AuthenticationContext authContext = new AuthenticationContext(authorityUri, new TokenCache());
private async void btnAuthenticate_ClickAsync(object sender, EventArgs e)
{
var authenticationResult = await authContext.AcquireTokenAsync(resourceUri, clientId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Auto));
if (authenticationResult == null)
MessageBox.Show("Call failed.");
else
MessageBox.Show(authenticationResult.AccessToken);
}
You can refer to the article about Power BI for .NET. Also you could use powershell to Resume-AzPowerBIEmbeddedCapacity.

Unable to retrieve access token using MSAL for Android

I've been trying to integrate my Android Application with Azure AD B2C using MSAL but I can't figure out how to retrieve my access token using a custom scope. I'm using this MSAL samples as a reference.
I already granted my application the needed permissions but i still get this message:
No access is found for scopes: https://rbxsoftb2c.onmicrosoft.com/rbx/get_access_token
Here's my Azure B2C settings, MSAL Constants and the API I'm trying to access :
MSAL Constants :
public class Constants {
/* Azure AD b2c Configs */
final static String AUTHORITY = "https://login.microsoftonline.com/tfp/%s/%s";
final static String TENANT = "rbxsoftb2c.onmicrosoft.com";
final static String CLIENT_ID = "MY_CLIENT_ID";
final static String SCOPES = "https://rbxsoftb2c.onmicrosoft.com/rbx/get_access_token";
final static String API_URL = "https://rbxsoft.azurewebsites.net/api/values";
final static String SISU_POLICY = "B2C_1_SiUpIn";
final static String EDIT_PROFILE_POLICY = "B2C_1_edit_profile";
}
My API :
[Produces("application/json")]
[Route("api/Values")]
[Authorize]
public class ValuesController : Controller
{
CosmosDatabaseConnection cdc = CosmosDatabaseConnection.Instance;
// GET: api/Values
[HttpGet]
public JValue Get()
{
AppState appState = SessionManager.GetCookieSession(HttpContext.Session, User);
return new JValue ( appState.User.profile.ToString() );
}
}

Xamarin Forms and Azure A2BC wrong login page

I have been trying to use Azure AD B2C with my Xamaerin.Forms iphone application. I've got it to sort of work following along based on this sample: active directory b2c xamarin native
The sample, though takes me to a login page that seems to only accept Microsoft Logins like this one:
This page seems to only let people log in with existing Microsoft accounts. I have set up my app to accept local email accounts, and I want the sign in page to look more like the link provided on the Azure AD B2C page:
This second version is the part of the login page that is displayed when using the "run now endpoint" on the AD B2C signin signup policy that looks as follows: https://login.microsoftonline.com/crowdwisdom.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_susi&client_id=0729f822-6c97-4b94-b75c-df4259b0f3c5&nonce=defaultNonce&redirect_uri=https%3A%2F%2Flogin.crowdwisdom.co&scope=openid&response_type=id_token&prompt=login
I don't understand which parameter of the AcquireTokenAsync method determines which page is delivered to the app
Here is the code I run that results in the top example:
public async void HandleSignIn()
{
try
{
AuthenticationResult ar = await App.PCA.AcquireTokenAsync(Constants.Scopes, GetUserByPolicy(App.PCA.Users, Constants.PolicySignUpSignIn), Constants.UiParent);
}
catch (Exception ex)
{
// Checking the exception message
// should ONLY be done for B2C
// reset and not any other error.
if (ex.Message.Contains("AADB2C90118"))
HandlePasswordReset();
// Alert if any exception excludig user cancelling sign-in dialog
else if (((ex as MsalException)?.ErrorCode != "authentication_canceled"))
throw ex;
}
}
private IUser GetUserByPolicy(IEnumerable<IUser> users, string policy)
{
foreach (var user in users)
{
string userIdentifier = Base64UrlDecode(user.Identifier.Split('.')[0]);
if (userIdentifier.EndsWith(policy.ToLower())) return user;
}
return null;
}
Constants definition:
public static class Constants
{
public static string Tenant = "foo.onmicrosoft.com";
public static string ClientID = "0729...-..."; //actual client id here.
public static string PolicySignUpSignIn = "B2C_1_susi";
public static string PolicyEditProfile = "B2C_1_edit_profile";
public static string PolicyResetPassword = "B2C_1_reset";
public static string[] Scopes = { "User.read" };
public static string ApiEndpoint = "https://foo.azurewebsites.net";
public static string AuthorityBase = $"https://login.microsoftonline.com/{Tenant}/oauth2/v2.0/authorize?p=";
private static string suffix = $"&client_id={ClientID}&nonce=defaultNonce&redirect_uri=https%3A%2F%2Fmyapi&scope=openid&response_type=id_token&prompt=login";
public static string Authority = $"{AuthorityBase}{PolicySignUpSignIn}{suffix}";
public static string AuthorityEditProfile = $"{AuthorityBase}{PolicyEditProfile}";
public static string AuthorityPasswordReset = $"{AuthorityBase}{PolicyResetPassword}";
public static UIParent UiParent = null;
}
Thanks for posting the code. When you use MSAL with AAD B2C, it's important that you indicate which policy you wish to use. That's how MSAL knows to invoke B2C functionality. What's happening right now is that you're not properly indicating which policy to use, and MSAL is defaulting back to the regular Microsoft login page, which only allows Microsoft personal & work/school accounts.
When using MSAL, the proper way to indicate policy is to use tfp in the path of the authority, like:
string BaseAuthority = "https://login.microsoftonline.com/tfp/mytenant.onmicrosoft.com/mypolicy";
See https://github.com/Azure-Samples/active-directory-b2c-xamarin-native/blob/master/UserDetailsClient/UserDetailsClient/App.cs#L25 for the most up-to-date example.
Yes, you can also use the p query string parameter to indicate policy, but the way you are passing it to MSAL causes MSAL to ignore it's existence and not include it in OAuth requests.
Last comment: you shouldn't have to deal with all those OAuth parameters in your suffix variable. MSAL will take care of that stuff for you.

Azure active directory and owin authentication

Just faced an strange issue with azure ad applicationS and owin openid authentication.
To reproduce the issue.
1.create a web app with azure ad authentication in vs 2015 choosing cloud app template .
2.let the standard code be as is.
3.let startup.auth as is.
4.Run the app on local it works fine.
5.now change code in startup àuth as follows
public partial class Startup
{
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
public static readonly string Authority = aadInstance + tenantId;
// This is the resource ID of the AAD Graph API. We'll need this to request a token to call the Graph API.
string graphResourceId = "https://graph.windows.net";
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public void ConfigureAuth(IAppBuilder app)
{
ApplicationDbContext db = new ApplicationDbContext();
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
logger.Debug("SetDefaultSignInAsAuthenticationType called");
//app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = ctx =>
{
//logger.Debug("OnResponseSignIn called");
////ctx.Identity = TransformClaims(ctx.Identity);
//logger.Debug("TransformClaims called");
}
}
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = Authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
// If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
AuthorizationCodeReceived = (context) =>
{
var code = context.Code;
ClientCredential credential = new ClientCredential(clientId, appKey);
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
logger.Debug("OnResponseSignIn called");
logger.Debug("signedInUserID =" + signedInUserID);
TransformClaims(context.AuthenticationTicket.Identity);
logger.Debug("TransformClaims called");
AuthenticationContext authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID));
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
return Task.FromResult(0);
},
// we use this notification for injecting our custom logic
SecurityTokenValidated = (context) =>
{
logger.Debug("SecurityTokenReceived called");
//TransformClaims(); //pass the identity
return Task.FromResult(0);
},
}
});
}
private static void TransformClaims(System.Security.Claims.ClaimsIdentity identity)
{
if (identity != null && identity.IsAuthenticated == true)
{
var usserobjectid = identity.FindFirst(ConfigHelpers.Azure_ObjectIdClaimType).Value;
((System.Security.Claims.ClaimsIdentity)identity).AddClaim(new System.Security.Claims.Claim("DBID", "999"));
((System.Security.Claims.ClaimsIdentity)identity).AddClaim(new System.Security.Claims.Claim("Super","True"));
}
// return identity;
}
}
6.Run the app on local it will work perfect.
7.Deploy the app on azure websites and the startup àuth owin notification methods will never be called.however app works but identity transformation not
Can somebody help out what's wrong with this is azure ad apps doesn't support cookies or notification not firing or anything wrong with code.
Just to re-assert else than startup.àuth no standard code is changed.
I know this is a bit old, but I had exactly the same issue recently and spent hours trying to understand why it wouldn't work in Azure but it worked absolutely fine in my localhost.
This is basically a configuration issue: in portal.azure.com select your app and then go to settings > authentication / authorisation and make sure that app service authentication is OFF.
It turns out that this setting will take over your startup.auth settings.
I have to give full credit to Vittorio Bertocci as pointed that out to me.

Resources