Showing posts with label azure Ad B2c. Show all posts
Showing posts with label azure Ad B2c. Show all posts

Friday, August 26, 2022

Get user list & details using Micorsoft graph api in c#

 In previous post I have shown how to use MS Graph Api to create users in Azure AD. Now Lets see how we can fetch and filter users using MS Graph Api. Go through the Setup Graph Api for uses of microsoft Graph Api from starting. This blog is continuous of the previous blog. To create project see Setup Graph Api.

Get All User By Page size 

Create class "UserData": For mapping Azure Ad user data.

 public class UserData
    {
        public string GivenName { get; set; }
        public string SurName { get; set; }
        public string Id { get; set; }
        public IEnumerable<ObjectIdentity> Identities { get; set; }
        public string DisplayName { get; set; }
        public string Email { get; set; }
        public string Country { get; set; }
        public string EmployeeId { get; set; }      
    }

Create another class "UserList" and paste below code


    public class UserList
    {
        public List<UserData> Users { get; set; }
        public string SkipToken { get; set; }     //in user object graph api return
//token for next paging ,if it reaches last token will be null  

    }

Now in your controller paste the below code

  [HttpGet]
        [Route("user-list")]
        public async Task<IActionResult> GetAllRegisterdUser(int pageSize=5,string pageNumer="")
        {
            var _graphClient = await GraphClientHelper.GetGraphApiClient(_configuration);
            var userList = new UserList();
            var queries = new List<QueryOption>();
            queries.Add(new QueryOption("$count","true"));
            queries.Add(new QueryOption("$top", pageSize.ToString()));        
            if (!string.IsNullOrWhiteSpace(pageNumer))
            {
                queries.Add(new QueryOption("$skiptoken", pageNumer));
            }

           var result = await _graphClient.Users
              .Request(queries)  
              //use if you need selected data
              .Select(x => new
              {
                  x.DisplayName,
                  x.Id,
                  x.Identities,
                  x.GivenName,
                  x.Mail,
                  x.Country,
                  x.Surname,
                  x.EmployeeId
              }).GetAsync();

            var data = result.CurrentPage.Select
                (p => new UserData
                {
                    DisplayName = p.DisplayName,
                    Country = p.Country,
                    Email = p.Mail,
                    EmployeeId = p.EmployeeId,
                    GivenName = p.GivenName,
                    Id = p.Id,
                    Identities = p.Identities,
                    SurName = p.Surname,
                }).ToList();

            userList.Users = data;
            userList.SkipToken = result.NextPageRequest?.QueryOptions?.FirstOrDefault(x =>
                       string.Equals("$skiptoken", x.Name, StringComparison.InvariantCultureIgnoreCase))?.Value;        


            return Ok(userList);

        }


Get user by search text :

 [HttpGet]
        [Route("user-search/{searchItem}")]
        public async Task<IActionResult> GetUserBySearch(string searchItem="",int pageSize = 5, string pageNumer = "")
        {
            var _graphClient = await GraphClientHelper.GetGraphApiClient(_configuration);
            var userList = new UserList();

            var queries = new List<QueryOption>();          
            queries.Add(new QueryOption("$top", pageSize.ToString()));
            if (!string.IsNullOrWhiteSpace(pageNumer))
            {
                queries.Add(new QueryOption("$skiptoken", pageNumer));
            }

            var result = await _graphClient.Users
               .Request(queries)
               .Filter(SetFilter(searchItem))
               //use if you need selected data
               .Select(x => new
               {
                   x.DisplayName,
                   x.Id,
                   x.Identities,
                   x.GivenName,
                   x.Mail,
                   x.Country,
                   x.Surname,
                   x.EmployeeId
               }).GetAsync();

            var data = result.CurrentPage.Select
                (p => new UserData
                {
                    DisplayName = p.DisplayName,
                    Country = p.Country,
                    Email = p.Mail,
                    EmployeeId = p.EmployeeId,
                    GivenName = p.GivenName,
                    Id = p.Id,
                    Identities = p.Identities,
                    SurName = p.Surname,
                }).ToList();

            userList.Users = data;
            userList.SkipToken = result.NextPageRequest?.QueryOptions?.FirstOrDefault(x =>
                       string.Equals("$skiptoken", x.Name, StringComparison.InvariantCultureIgnoreCase))?.Value;


            return Ok(userList);

        }

 private string SetFilter(string searchItem)
        {
            if (string.IsNullOrWhiteSpace(searchItem))
            {
                return string.Empty;
            }

            return $"startswith(givenName, '{searchItem}')" +
                   $" or startswith(surname, '{searchItem}')"+
                    $" or startswith(displayName, '{searchItem}')" ;
         
        }


Get user by Email Id / Identity  :

[HttpGet]
        [Route("search-by-email/{emailId}")]
        public async Task<IActionResult> GetUserByEmail(string emailId)
        {
            var _graphClient = await GraphClientHelper.GetGraphApiClient(_configuration);
            var userList = new UserList();

            var result = await _graphClient.Users
               .Request()
               .Filter($"identities/any(c:c/issuerAssignedId eq '{emailId}' and c/issuer eq '{tenant url}') ")
               .Select(x => new
               {
                   x.DisplayName,
                   x.Id,
                   x.Identities,
                   x.GivenName,
                   x.Mail,
                   x.Country,
                   x.Surname,
                   x.EmployeeId
               }).GetAsync();
            return Ok(result);

        }


Get user by User Id:

 [HttpGet]
        [Route("search-by-Id/{userId}")]
        public async Task<IActionResult> GetUserById(string userId)
        {
            var _graphClient = await GraphClientHelper.GetGraphApiClient(_configuration);
            var result = await _graphClient.Users[userId]
               .Request()
               .GetAsync();
            return Ok(result);

        }


await GraphClientHelper.GetGraphApiClient(_configuration); //to configure this you follow Setup Graph Api.



 you can download all the azure samples code : https://github.com/mkumar8184/azure-sdk-services-samples

Thursday, July 28, 2022

Customize Default Signup/Sign In pages in azure ad B2C

In Previous tutorial I explained how to use Azure AD B2C . This tutorial is a continuous  part of the previous tutorial. Here I will show how we can customize default Pages for sign up/Sign In .

Why to customize: Microsoft provides default page without branding and different theme which may not be match with any company branding /application . So just need to unified and seamless user experience better to customize page.

Default Page :


Customized Signup /Sing In page will look like - of course you can design better than this.



In order to achieve this we need 3 things to do

1. Prepare one html page  with required css/js (can be inline or external css class)
2. Upload in storage or somewhere so it can be accessed from B2C
3. Customize the user flow from default to your html page

1. Html Page : I am creating with inline css if you want you can add external css ref. Also I have used some online customized bootstrap just to make it nicer. But sure you can make it better. Purpose is just to see how can we customize

Html Code :

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Azure B2C change login page</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://www.markuptag.com/bootstrap/5/css/bootstrap.min.css">
    <style type="text/css">
        body {
            background-color: #4887e6;
            font-family: Verdana;
            font-size: 14px;
        }
        .bg-light {
           background-color:#dde4eb !important;
        }
        h2 {
            font-size: medium !important;
            color: blue !important;
        }
        #next {
            background-color: #4CAF50; /* Green */
            border: none;
            color: white;
            padding: 15px 32px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 16px;
        }
        button {
            background-color: #4CAF50 !important; /* Green */
            border: none !important;
            color: white !important;
            padding: 10px 20px !important;
            text-align: center !important;
            text-decoration: none !important;
            display: inline-block !important;
            font-size: 14px !important;
            margin: 2px 2px 2px 2px !important;
        }
        input[type=email] {
            width: 100%;
            box-sizing: border-box;
            border: 2px solid #ccc;
            border-radius: 4px;
            font-size: 16px;
            background-color: white;
            background-image: url('searchicon.png');
            background-position: 10px 10px;
            background-repeat: no-repeat;
            padding: 12px 20px 12px 40px;
            margin-bottom: 3px !important;
        }
        .dropdown_single {
            width: 100%;
            box-sizing: border-box !important;
            border: 2px solid #ccc !important;
            border-radius: 4px !important;
            font-size: 16px !important;
            background-color: white !important;
            background-image: url('searchicon.png') !important;
            background-position: 10px 10px !important;
            background-repeat: no-repeat !important;
            padding: 12px 20px 12px 40px !important;
            margin-bottom: 3px !important;
        }
        input[type=password] {
            width: 100%;
            box-sizing: border-box;
            border: 2px solid #ccc;
            border-radius: 4px;
            font-size: 16px;
            background-color: white;
            background-image: url('searchicon.png');
            background-position: 10px 10px;
            background-repeat: no-repeat;
            padding: 12px 20px 12px 40px;
            margin-bottom: 3px !important;
        }
        input[type=text] {
            width: 100%;
            box-sizing: border-box;
            border: 2px solid #ccc;
            border-radius: 4px;
            font-size: 16px;
            background-color: white;
            background-image: url('searchicon.png');
            background-position: 10px 10px;
            background-repeat: no-repeat;
            padding: 12px 20px 12px 40px;
            margin-bottom: 3px !important;
        }
        .buttons {
            margin-top:2px!important;
        }
        ul {
            list-style: none !important;
            padding-inline-start: 20px !important;
        }
        a {
            color: #8caad8 !important;
            text-decoration: underline !important;
        }
       
    </style>
</head>
<body>

    <div class="container">
        <div class="row">
            <div class="col-md-8 offset-md-4">
                <div class="login-form bg-light mt-4 p-4">
                    <h4>Welcome To Azure AD B2C Example</h4>
                    <hr class="mt-2">
                    <div id="api" class="row g-3">

                    </div>

                    <hr class="mt-4">

                </div>
            </div>
        </div>
    </div>

    <!-- Bootstrap JS -->
    <script src="https://www.markuptag.com/bootstrap/5/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Html output will look like  without form .




in the above code you can design based on your branding , header ,footer . only thing that you need to add is below tag .where on render time Microsoft insert required form. Div/section Id must be "api"

 <div id="api" class="row g-3">

</div>


2. Upload html and css file to Storage :  upload this file to my storage 
Go to storage account -> container -> create new container/select existing one-> upload your html file.


Uploaded file :


Go back to storage account and enable CORS to have access this storage file from external place.
Type CORS in search in left top and click ok


Allowed Origins: enter your organization instance/url name 
Method - Get, options
Rest field you can put *  and save .

3. Use in User Flow :
Go to Azure B2C tenants and from left menu click user flow and select B2C_1_singupsing" which you have create in previous part.



Click Page Layout and select 
1. unified signup and sign in 
2. user custom page content - Yes
3.custom page url- need to enter your html file url. to copy the url you can go to the file and click .you will see url which you need to copy






After updating custom page url click on save ,Now you can test your customized page .
To test this either you can run your application or click on "Run User Flow" directly .
And here you go to your pages:

Sign In :

sign Up:



And we are done with customizing the default pages in B2C. 

 you can download all the azure samples code : https://github.com/mkumar8184/azure-sdk-services-samples


Convert Html to Pdf in azure function and save in blob container

 In this post  I am going to create an azure function ( httpTrigger ) and send html content  which will be converted into PDF and save in bl...