Sharun shetty
Sharun shetty

Reputation: 1

Not able to integrate scim api to okta

I want to connect my scim api to okta for user provisioning. Not able to integate scim API with okta. Also not aware of the steps to do the integration. Any help would be highly appreciated.

I am providing the scim api code which i am going to integrate with okta.

UserController

using System.Net;
using System.Security.Principal;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using ScimConnector1.Models;
using System.Threading;
using System.Net;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using ScimConnector1.BasicAuth;
using Group = ScimConnector1.Models.Group;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using static System.Net.Mime.MediaTypeNames;
using System.Net.Http.Formatting;

namespace ScimConnector1.Controllers
{
    [Authorize]
    [Route("scim/v2/[controller]")]
    [ApiController]
    //[BasicAuthentication]
    public class UsersController : ControllerBase
    {
        ScimApi scimApi = new ScimApi();

        //Create User
        [HttpPost]
        public HttpResponseMessage PostUser([FromBody] User userObject)
        {
            // Map the SCIM user to a local user object
            var user = new User
            {
                id = userObject.id,
                userName = userObject.userName,
                name =new Name 
                {
                    givenName = userObject.name.givenName,
                    familyName = userObject.name.familyName,
                },
                emails = userObject.emails,
            };

            try
            {
                scimApi.AddUserToStore(user);
            }
            catch (Exception ex)
            {
                // Handle any errors that occur during user creation
                return new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    Content = new StringContent(ex.Message),
                    ReasonPhrase = "Error while creating user"
                };
            }

            // Return the SCIM representation of the created user
            var createdScimUser = new User
            {
                id = user.id,
                userName = user.userName,
                name=new Name
                {
                    givenName = user.name.givenName,
                    familyName = user.name.familyName,
                },
                emails = user.emails,
            };

            var response = new HttpResponseMessage(HttpStatusCode.Created)
            {
                Content = new ObjectContent<User>(createdScimUser, new JsonMediaTypeFormatter()),
            };

            response.Headers.Location = new Uri($"{Request.Scheme}://{Request.Host}/Groups/{createdScimUser.userName}");

            return response;
        }

        //Get User
        [HttpGet]
        public IActionResult GetUser(string id)
        {
            // get user from your application here
            User existingUser = scimApi.GetUserById(id);

            // if user is not found in application, return 404
            if (existingUser == null)
            {
                return NotFound();
            }
            else
            {
                return Ok(existingUser);
            }
        }

        //Put user[update user]
        [HttpPut]
        public IActionResult UpdateUser(string id, [FromBody] User user)
        {
            // Implement your logic for updating a user by ID
            User existingUser = scimApi.GetUserById(id);

            if (existingUser == null)
            {
                return NotFound();
            }
            //existingUser.id = user.id;
            existingUser.userName = user.userName;
            existingUser.name = new Name
            {
                givenName = user.name.givenName,
                familyName = user.name.familyName
            };
            existingUser.emails = user.emails;

            // Update the user in your database or external system
            scimApi.UpdateUserInDb
                (existingUser.id, existingUser.userName, existingUser.name.familyName, existingUser.name.givenName, existingUser.emails);

            return Ok(existingUser);

            //return Ok(user);
        }

    }
}

GroupController

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ScimConnector1.Models;
using System.Net;

namespace ScimConnector1.Controllers
{
    [Authorize]
    [Route("scim/v2/[controller]")]
    [ApiController]
    public class GroupsController : ControllerBase
    {
        ScimApi scimApi = new ScimApi();



        [HttpPost]  //create Group
        public IActionResult CreateGroup([FromBody] Group scimGroup)
        {
            // Map the SCIM group to a local Group object
            var group = new Group
            {
                //Id = scimGroup.ExternalId,
                DisplayName = scimGroup.DisplayName,
                Description = scimGroup.Description,
                //Members = scimGroup.Members.Select(m => m.id).ToList()
                //Members = new List<string>()
            };


            // Create the group in the database using the local group object
            try
            {
                scimApi.CreateGroupInDb(group);
            }
            catch (Exception ex)
            {
                // Handle any errors that occur during group creation
                return StatusCode(500, ex.Message);
            }

            // Return the SCIM representation of the created group
            var createdScimGroup = new Group
            {
                //Id = group.Id,
                //ExternalId = group.Id,
                DisplayName = group.DisplayName,
                Description = group.Description,
                //Members = scimGroup.Members.Select(m => new User { id = m}).ToList()
            };

            return Created($"{Request.Scheme}://{Request.Host}/Groups/{createdScimGroup.DisplayName}", createdScimGroup);
        }


        [HttpGet]  //get Group
        public HttpResponseMessage GetGroup(HttpRequestMessage request, string id)
        {
            Group existingGroup = scimApi.GetGroupById(id);
            // get group from app

            if (existingGroup != null)
            {
                return request.CreateResponse(HttpStatusCode.OK, existingGroup);
            }
            else
            {
                return request.CreateResponse(HttpStatusCode.NotFound);
            }
        }




        [HttpPut]  //update Group
        public IActionResult PutGroup(String id, Group group)
        {
            // update group in app
            Group existingGroup = scimApi.GetGroupById(id);

            if (existingGroup == null)
            {
                return NotFound();
            }
            //existingUser.id = user.id;
            existingGroup.DisplayName = group.DisplayName;
            existingGroup.Description = group.Description;

            // Update the user in your database or external system
            scimApi.UpdateGroupInDb(id, existingGroup.DisplayName, existingGroup.Description);

            return Ok(existingGroup);




        }

    }
}

ScimApi.cs: where all the methods which is called by the controllers are present

using System.Data;
using System.Data.SqlClient;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Npgsql;

namespace ScimConnector1.Models
{
    public class ScimApi
    {
        public string connectionString = "Port=XXXXX; Host=XXXXXXXX; Database=XXXXX;User Id=XXXXX;Password=XXXXX;";

      

        public void AddUserToStore(User user)
        {
            // Add the user to your app's user store
            
            // create a new database connection using the provided connection string
            using (var conn = new 
                       NpgsqlConnection(connectionString))
            {
                // open the database connection
                conn.Open();

                var command = new NpgsqlCommand("INSERT INTO Users (Id, UserName, FirstName, LastName, Email) " +
                                                "VALUES (@Id, @UserName, @FirstName, @LastName, @Email)", conn);

                command.Parameters.AddWithValue("@Id", user.id);
                command.Parameters.AddWithValue("@UserName", user.userName);
                command.Parameters.AddWithValue("@FirstName", user.name.givenName);
                command.Parameters.AddWithValue("@LastName", user.name.familyName);
                command.Parameters.AddWithValue("@Email", user.emails);

                int rowsAffected = command.ExecuteNonQuery();

                if (rowsAffected != 1)
                {
                    throw new Exception($"Failed to insert user with id {user.id} into database.");
                }

            }
        }

       
        public User GetUserById(string id)
        {
            User user = null;

            using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
            {
                connection.Open();

                using (NpgsqlCommand command = new NpgsqlCommand("SELECT * FROM users WHERE id = @id", connection))
                {
                    command.Parameters.Add(new NpgsqlParameter("id", DbType.String)).Value = id;

                    using (NpgsqlDataReader reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            user = new User
                            {
                                id = reader.GetString(reader.GetOrdinal("id")),
                                userName = reader.GetString(reader.GetOrdinal("username")),
                                name=new Name
                                {
                                    givenName = reader.GetString(reader.GetOrdinal("firstName")),
                                    familyName = reader.GetString(reader.GetOrdinal("lastName")),
                                },
                                emails = reader.GetString(reader.GetOrdinal("email"))
                            };
                        }
                    }
                }
            }

            return user;
        }



        public void UpdateUserInDb(string id, string userName, string firstName, string lastName, string email)
        {
            using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
            {
                connection.Open();

                using (NpgsqlCommand command = new NpgsqlCommand("UPDATE users SET username=@userName, firstName = @firstName, lastName = @lastName, email = @email WHERE id = @id", connection))
                {
                    command.Parameters.AddWithValue("@id", id);
                    command.Parameters.AddWithValue("@username", userName);
                    command.Parameters.AddWithValue("@firstName", firstName);
                    command.Parameters.AddWithValue("@lastName", lastName);
                    command.Parameters.AddWithValue("@email", email);

                    command.ExecuteNonQuery();
                }
            }
        }


        public Group GetGroupById(string id)
        {

            Group group = null;

            using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
            {
                connection.Open();

                using (NpgsqlCommand command = new NpgsqlCommand("SELECT * FROM groups WHERE id = @id", connection))
                {
                    command.Parameters.Add(new NpgsqlParameter("id", DbType.String)).Value = id;

                    using (NpgsqlDataReader reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            group = new Group
                            {
                                //id = reader.GetString(reader.GetOrdinal("id")),
                                DisplayName = reader.GetString(reader.GetOrdinal("displayname")),
                                Description = reader.GetString(reader.GetOrdinal("description")),
                            };
                        }
                    }
                }
            }

            return group;
        }


       

       public void UpdateGroupInDb(string id ,string DisplayName,string Discription)
        {
            using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
            {
                connection.Open();

                using (NpgsqlCommand command = new NpgsqlCommand("UPDATE groups SET DisplayName=@displayName, description= @Description WHERE id = @id", connection))
                {
                    //command.Parameters.AddWithValue("@id", id);
                    command.Parameters.AddWithValue("@DisplayName", DisplayName);
                    command.Parameters.AddWithValue("@Description", Discription);

                    command.ExecuteNonQuery();
                }
            }
        }

        public void CreateGroupInDb(Group group)
        {
            //string connectionStringToGroup = "Server=TestServer;Port=2001; Host=127.0.0.1; Database=groups;User Id=Drona;Password=12345;";
            using (var connection = new NpgsqlConnection(connectionString))
            {
                connection.Open();

                using (var command = new NpgsqlCommand("INSERT INTO groups (displayname,discription) VALUES (@displayName,@discription)", connection))
                {
                    //command.Parameters.AddWithValue("id", group.Id);
                    command.Parameters.AddWithValue("displayName", group.DisplayName);
                    command.Parameters.AddWithValue("discription", group.Description);
                    //command.Parameters.AddWithValue("members", JsonConvert.SerializeObject(group.Members));

                    command.ExecuteNonQuery();
                }

                connection.Close();
            }
        }
    }
}

This is the scim API code that I am using to integrate with okta. here I want my scim API to transfer data from okta to my app( ryt now its the database). Also hosted the above code in azure. please let me know the proper way now to integrate the above scim API code with okta. I am using basic authentication in the scim API.

![1]: https://i.sstatic.net/4QVKv.png

This image is of the okta platform, the app in okta is scim api test app(basic auth).

In the image where I have given the base URL of my scim api with the authentication credential.When I click "Test api credential" I am getting the error as "Error authenticating: Bad Request. Errors reported by the remote server:"(as in the image).

Please let me know the changes to be done in my api or let me know the proper steps to be followed for scim integration.

Upvotes: 0

Views: 424

Answers (0)

Related Questions