1

Je suis nouveau sur C# et Azure AD, alors n'hésitez pas à me donner quelques conseils et ressources pour savoir comment autoriser uniquement l'authentification unique et l'autorisation pour mon application MVC. ma liste de clients approuvés. J'ai une petite application que j'héberge sur une machine virtuelle Azure et qui utilise Azure AD avec Azure AD en utilisant OpenID Connect. J'ai fait l'inscription de l'application multi-locataire dans Azure AD. J'ai mis en place un nouveau compte org avec certains utilisateurs pour tester dans Azure AD. Je lis this guide, ce qui est bon, mais s'arrête en notant dans ses exemplesMeilleures pratiques d'authentification multiclient et de filtrage d'authentification Azure AD

validation de l'émetteur est désactivé pour permettre à tout locataire Azure AD pour vous connecter

Je ne peux pas trouver guide pour savoir comment qualifier le locataire comme une organisation, je veux accéder à mon application. Quelle est la meilleure façon d'autoriser des utilisateurs, disons, du domaine CustomerCompany.com mais pas SomeOtherCompany.com même si les deux ont des comptes org azur AD?

Je ne souhaite pas gérer la liste des utilisateurs. Par conséquent, les éléments B2B de la collaboration Azure AD ne remplissent pas la facture (chargement des listes d'utilisateurs et émission d'invitations). Je voudrais que le client maintienne sa propre liste d'utilisateurs.

Je veux d'abord simplement autoriser les utilisateurs de mes clients et refuser tous les autres.

  • Y a-t-il un moyen de créer une relation entre mon organisation et les autres utilisateurs d'Azure AD et d'autoriser/refuser l'autorisation à mon application via ces relations lors de la connexion AAD?
  • Existe-t-il une valeur tenantid provenant d'Azure AD que je peux comparer à une liste conservée dans le serveur SQL pour autoriser/refuser l'autorisation après la connexion AAD? Est-ce typiquement un nom de domaine ou un GUID ou une autre valeur que je dois obtenir du client?

Si le client veut limiter l'utilisation de mon application à certaines personnes dans leur org est-il la meilleure pratique à:

  • Demandez le registre client mon application ou attribuer une certaine façon à des groupes qu'ils mettent en leur propre Azure AD afin que l'utilisateur ne s'authentifiera pas si non autorisé par leur administrateur? OU
  • Interrogez le profil d'utilisateur entrant sur mon serveur pour obtenir une certaine valeur (appartenance à un groupe, service, gestionnaire, etc.) à l'aide de l'API graphique et autoriser/refuser en fonction de cette valeur?

Nous vous saurions gré de toutes les instructions pratiques et pratiques que vous pouvez fournir à un débutant. Je vous remercie.

Répondre

1

Y a-t-il un moyen de créer une relation entre mon organisation et les autres utilisateurs dans Azure AD et d'autoriser/refuser l'autorisation à mon application en utilisant ces relations lors de la connexion AAD?

Existe-t-il une valeur tenantid provenant d'Azure AD que je peux comparer à une liste conservée dans le serveur SQL pour autoriser/refuser l'autorisation après la connexion AAD? Est-ce typiquement un nom de domaine ou un GUID ou une autre valeur que je dois obtenir du client?

Oui. Nous sommes en mesure d'écrire le code personnalisé pour vérifier la revendication iss à partir de jeton pour le faire correspondre à la logique métier.Voici le code en utilisant le composant OWIN pour votre OpenID Connect Référence:

app.UseOpenIdConnectAuthentication(
      new OpenIdConnectAuthenticationOptions 
      { 
       ClientId = ClientId, 
       Authority = Authority, 
       TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters 
       { 
        // instead of using the default validation (validating against a single issuer value, as we do in line of business apps), 
        // we inject our own multitenant validation logic 
        ValidateIssuer = false, 
       }, 
       Notifications = new OpenIdConnectAuthenticationNotifications() 
       { 

        // we use this notification for injecting our custom logic 
        SecurityTokenValidated = (context) => 
        { 
         // retriever caller data from the incoming principal 
         string issuer = context.AuthenticationTicket.Identity.FindFirst("iss").Value; 
         string UPN = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value; 
         string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; 

         if (
          // the caller comes from an admin-consented, recorded issuer 
          (db.Tenants.FirstOrDefault(a => ((a.IssValue == issuer) && (a.AdminConsented))) == null) 
          // the caller is recorded in the db of users who went through the individual onboardoing 
          && (db.Users.FirstOrDefault(b =>((b.UPN == UPN) && (b.TenantID == tenantID))) == null) 
          ) 
          // the caller was neither from a trusted issuer or a registered user - throw to block the authentication flow 
          throw new SecurityTokenValidationException();        
         return Task.FromResult(0); 
        }, 
        AuthenticationFailed = (context) => 
        { 
         context.OwinContext.Response.Redirect("/Home/Error?message=" + context.Exception.Message); 
         context.HandleResponse(); // Suppress the exception 
         return Task.FromResult(0); 
        } 
       } 
      }); 

Et here est un exemple de code utile pour votre référence. Le client peut-il enregistrer mon application ou l'attribuer à des groupes qu'il a configurés dans son propre Azure AD afin que l'utilisateur ne puisse pas s'authentifier s'il n'est pas autorisé par son administrateur? OU

Interrogez le profil d'utilisateur entrant sur mon serveur pour obtenir une valeur (appartenance à un groupe, service, gestionnaire, etc.) à l'aide de l'API graphique et autoriser/refuser en fonction de cette valeur? D'après ce que je comprends, il devrait permettre à l'entreprise personnalisée de gérer les utilisateurs qui ont accès à votre application parce que la gestion des utilisateurs est responsable de la société des partenaires. Ainsi, après que l'entreprise des partenaires a décidé d'activer/désactiver les utilisateurs, votre entreprise et votre application n'ont pas besoin de faire ou de travailler ou de changer.

Et pour gérer les utilisateurs qui peuvent accéder à l'application, la société des partenaires peut utiliser la fonctionnalité Requiring User Assignment.

0

Merci. Je réponds également à mon propre Q pour ajouter plus de détails à la façon dont j'ai progressé (j'espère que cela aide un lecteur) et pour poser une question plus détaillée pour en arriver au bout. J'ai maintenant un moyen de comparer les données graphiques d'un utilisateur authentifié entrant à une liste de noms de sociétés clients que je garde. Mais ce n'est pas idéal. Cela dépend de l'affichage de l'adresse graphique du client displayName du locataire, qui devrait correspondre à ma liste. Je crains que cela puisse changer, puis interdire les clients légitimes. Je préférerais utiliser l'ID du locataire d'Azure AD. Mais je ne sais pas comment l'obtenir dès mon inscription. Je peux l'obtenir après que le premier utilisateur s'authentifie à partir de ce locataire, mais comment puis-je obtenir l'ID de client du client avant que quelqu'un de cette société ne s'authentifie? Dois-je le demander, ou puis-je l'obtenir moi-même?

Existe-t-il un meilleur moyen de filtrer l'accès à mon application Web (IIS) pour autoriser uniquement mes clients? C'est mon Q détaillé.

S'il vous plaît aider un débutant comprendre comment les grands garçons autorisent seulement leurs clients à une application web IIS. Voici le début de la façon dont je le fais (tricher avec le pseudo code dans la partie filtrage des clients parce que je voudrais comparer un GUID comme TenantID (Issuer?) Plutôt qu'une chaîne comme DisplayName):

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 postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"]; 
    public static string custTenantID = ""; 

    //for multi tenant sso, can be 'common' for consumer, 'organization' for work+school, or tenantID for single company 
    public static readonly string Authority = aadInstance + "common/"; 

    //this is my model for the customer db 
    public CustomerTenant tenant = new CustomerTenant(); 

    // 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"; 


    public void ConfigureAuth(IAppBuilder app) 
    {  
     ApplicationDbContext db = new ApplicationDbContext(); 

     app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 

     app.UseCookieAuthentication(new CookieAuthenticationOptions()); 

     app.UseOpenIdConnectAuthentication(
      new OpenIdConnectAuthenticationOptions 
      { 
       ClientId = clientId, 
       Authority = Authority, 
       PostLogoutRedirectUri = postLogoutRedirectUri, 


       //for multi-tenant 
       TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters 
       { 
        // instead of using the default validation (validating against a single issuer value, as we do in line of business apps) 
        // we inject our own multitenant validation logic 
        ValidateIssuer = false, 
       }, 

       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 is invoked after SecurityTokenValidated 
//using this Notification to inject logic to authorize only my customers 
        AuthorizationCodeReceived = (context) => 
        { 
         var code = context.Code; 
         ClientCredential credential = new ClientCredential(clientId, appKey); 
         string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value; 
         Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(Authority, new ADALTokenCache(signedInUserID)); 

         AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
         code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId); 

//look up the customer tenant's DisplayName to compare to my list 
         Uri servicePointUri = new Uri(graphResourceId); 
         Uri serviceRoot = new Uri(servicePointUri, custTenantID); 
         ActiveDirectoryClient client = new ActiveDirectoryClient(serviceRoot, async() => { return await Task.FromResult(result.AccessToken); }); 
         string tenantName = client.TenantDetails.ExecuteAsync().Result.CurrentPage.First().DisplayName; 

//pseudo-code: compare this tenantName to db.CustomerTenants.CustomerName and if there is a match then authorize else do not authorize 

         return Task.FromResult(0); 

        }, 


        //for multi-tenant sso 
        RedirectToIdentityProvider = (context) => 
        { 
         string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase; 
         context.ProtocolMessage.RedirectUri = appBaseUrl; 

         context.ProtocolMessage.PostLogoutRedirectUri = postLogoutRedirectUri; 
         return Task.FromResult(0); 
        }, 


        SecurityTokenValidated = (context) => 
        { 
         // retrieve caller data from the incoming principal 
         string issuer = context.AuthenticationTicket.Identity.FindFirst("iss").Value; 
         string UPN = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value; 
         custTenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; 


         return Task.FromResult(0); 
        }, 

        AuthenticationFailed = (context) => 
        { 

        context.OwinContext.Response.Redirect("urlToMyErrorPage?message=" + context.Exception.Message); 
         context.HandleResponse(); // Suppress the exception 
         return Task.FromResult(0); 
        } 
      } 
     }); 

    }