Authentication types

The Sage Construction Management API supports 3 methods for authentication using OAuth 2.0 to provide secure access to the resources.

Method 1: Authorization Code Grant Flow

In the Authorization Code Grant flow, your client integration first obtains consent from an individual to act on their behalf, then receives an authorization code, which can be exchanged for an access token needed to make API calls.

Prerequisites

  • - Integration Key or Client Id: An integration key identifies your integration and links to its configuration values.

  • - Secret Key: A secret key is a value that is stored securely in your web server and is shared only between your web server and the Sage Construction Management platform.

  • - Redirect URI: The redirect URI is the URI (URL) to which Sage Construction Management will redirect the browser after authentication.

Steps to get an access token

To get the authorization code, structure the URL as follows:

Endpoint_URL/Authorization?response_type=code&scopes=Scope&state=State&client_id=Client_ID&redirect_uri=Redirect_URI

Where:
  • - Endpoint_URL is the Sage Construction Management authorization API URL.

  • - Scope is one of the following authorization scopes:

    • -- add
    • -- read
    • -- edit
    • -- add,read
    • -- read,edit
    • -- add,read,edit

  • - State is the authorization state. For example, wqcorcf-#$%HY5.

  • - ClientID is the access client code. For example, f28d637d-XXXXX-7f27-XXXX-889b529c2bf1.

  • - RedirectUrl is the URL of the client application. For example, https://mycustomdomain.com/callback. For testing, this URL can be set to your local environment, for example, http://localhost:4200/callback.

Example

  1. 1. The user enters the following URL:

    Endpoint_URL/Authorization?response_type=code&scopes=add,read,edit&state=state1&client_id=9d1XXXXX-2822-XXXXX-3734-cf5bXXXXXed0&redirect_uri=http://localhost:4200/callback

    Result: A prompt is displayed to the user, requesting their confirmation to grant access to your application through the API.

  2. 2. The user selects Allow.

    Result: The user is redirected to the Redirect URL with the appropriate authorization code and state, and the URL will conform to the following structure: Redirect_URI?code=Authorization_Code&state=State.

  3. 3. To get the access token, the user makes an HTTP POST request to the API endpoint including the code, state, redirect_uri, and the authorization_code as grant_type.

    For example:

                                
            public async Task GetAccessToken(string code, string state)
            {
                byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(client_id + ":" + secret_key);
                string key = System.Convert.ToBase64String(plainTextBytes);
                HttpClient _client = new HttpClient
                {
                BaseAddress = new Uri(ConstantValue.BaseAddress + "token")
                };
                _client.DefaultRequestHeaders.Accept.Clear();
                _client.DefaultRequestHeaders.Add("authorization", "Basic " + key);
                _client.DefaultRequestHeaders.Add("Access-Control-Allow-Origin", "*");
                _client.DefaultRequestHeaders.Add("No-Auth", "true");
                _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
                HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, ConstantValue.BaseAddress + "token")
                {
                Content = new FormUrlEncodedContent(new Dictionary
                {
                    { "grant_type", "authorization_code" },
                    { "redirect_uri", ConstantValue.redirect_uri },
                    { "code", code },
                    { "state", state }
                })};
                    HttpResponseMessage response = await _client.SendAsync(requestMessage);
                    if (response.IsSuccessStatusCode)
                    {
                        HttpContent responseContent = response.Content;
                        string responseString = responseContent.ReadAsStringAsync().Result;
                        dynamic tokenInfo = JObject.Parse(responseString);
                        Token token = new Token
                        {
                        AccessToken = tokenInfo.access_token,
                        ExpiresIn = tokenInfo.expires_in,
                        RefreshToken = tokenInfo.refresh_token,
                        TokenType = tokenInfo.token_type
                        };
                        TempData["Token"] = token;
                        return View(token);
                    }
                    else
                    {
                        return View();
                    }
                }
        
    

    Result: The API response conforms to the following format:

    {"access_token":"Access_Token","refresh_token":"Refresh_Token", "expires_in":302, "token_type":"bearer"}

Method 2: Resource Owner Password Credentials Grant Flow

Prerequisites

  • - Integration Key or Client Id: An integration key identifies your integration and links to its configuration values.

  • - Secret Key: A secret key is a value that is stored securely in your web server and is shared only between your web server and the Sage Construction Management platform.

  • - User Name: The username associated with the Sage Construction Management account.

  • - Password: The Sage Construction Management account password.

Steps to get an access token
  1. 1. Make an HTTP POST request to the API endpoint including the username, password, scope, and password as grant_type.

    For example:

                                
                                public async Task Index(CredModel credModel)
                                {
                                    byte[] plainTextBytes = Encoding.UTF8.GetBytes(credModel.ClientID + ":" + credModel.SecretCode);
                                    string key = System.Convert.ToBase64String(plainTextBytes);
                                    HttpClient _client = new HttpClient
                                    { 
                                        BaseAddress = new Uri(ConstantValue.BaseAddress + "token") };
                                        _client.DefaultRequestHeaders.Accept.Clear();
                                        _client.DefaultRequestHeaders.Add("authorization", "Basic " + key);
                                        _client.DefaultRequestHeaders.Add("Access-Control-Allow-Origin", "*");
                                        _client.DefaultRequestHeaders.Add("No-Auth", "true");
                                        _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
                                        HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, ConstantValue.BaseAddress + "token")
                                        {
                                        Content = new FormUrlEncodedContent(new Dictionary{
                                            { "grant_type", "password" },
                                            { "username", credModel.UserName },
                                            { "password", credModel.Password },
                                            { "scope", credModel.Scopes }
                                        })};
                                        HttpResponseMessage response = await _client.SendAsync(requestMessage);
                                        if (response.IsSuccessStatusCode)
                                        {
                                            HttpContent responseContent = response.Content;
                                            string responseString = responseContent.ReadAsStringAsync().Result;
                                            dynamic tokenInfo = JObject.Parse(responseString);
                                            Token token = new Token
                                            {
                                                AccessToken = tokenInfo.access_token,
                                                ExpiresIn = tokenInfo.expires_in,
                                                RefreshToken = tokenInfo.refresh_token,
                                                TokenType = tokenInfo.token_type
                                            };
                                            return View(token);
                                        }
                                        else
                                        {
                                            return View("Index", "Home");
                                        }
                                }
                            
                        

    Result: The API response conforms to the following format:

    {"access_token":"Access_Token","refresh_token":"Refresh_Token", "expires_in":302, "token_type":"bearer"}

Method 3: Client Credential Grant Flow

Prerequisites

  • - Integration Key or Client Id: An integration key identifies your integration and links to its configuration values.

  • - Secret Key: A secret key is a value that is stored securely in your web server and is shared only between your web server and the Sage Construction Management platform.

  • - Redirect URI: The URI to send the access token.

Steps to get an access token
  1. 1. Make an HTTP POST request to the API endpoint including the username, password, scope, and client_credentials as grant_type.

    For example:

                                
                                public async Task Index(CredModel credModel)
                                {
                                    byte[] plainTextBytes = Encoding.UTF8.GetBytes(credModel.ClientID + ":" + credModel.SecretCode);
                                    string key = System.Convert.ToBase64String(plainTextBytes);
                                    HttpClient _client = new HttpClient
                                    { BaseAddress = new Uri(ConstantValue.BaseAddress + "token") };
                                    _client.DefaultRequestHeaders.Accept.Clear();
                                    _client.DefaultRequestHeaders.Add("authorization", "Basic " + key);
                                    _client.DefaultRequestHeaders.Add("Access-Control-Allow-Origin", "*");
                                    _client.DefaultRequestHeaders.Add("No-Auth", "true");
                                    _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
                                    HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, ConstantValue.BaseAddress + "token")
                                    {
                                    Content = new FormUrlEncodedContent(new Dictionary {
                                        { "grant_type", "client_credentials" },    
                                        { "scope", credModel.Scopes }
                                    })};
                                    HttpResponseMessage response = await _client.SendAsync(requestMessage);
                                    if (response.IsSuccessStatusCode)
                                    {
                                        HttpContent responseContent = response.Content;
                                        string responseString = responseContent.ReadAsStringAsync().Result;
                                        dynamic tokenInfo = JObject.Parse(responseString);
                                        Token token = new Token
                                        {
                                        AccessToken = tokenInfo.access_token,
                                        ExpiresIn = tokenInfo.expires_in,
                                        RefreshToken = tokenInfo.refresh_token,
                                        TokenType = tokenInfo.token_type
                                        };
                                        return View(token);
                                    }
                                    else
                                    {
                                        return View("Index", "Home");
                                    }
                                }
                            
                        

    Result: The API response conforms to the following format:

    {"access_token":"Access_Token","refresh_token":"Refresh_Token", "expires_in":302, "token_type":"bearer"}