Webservices

Webservices

This application also offers webservices for uploading/download classified productdata. You can upload productdata with the /EtimUp/NewWorkload webservices. After upload, you can use this web application to view and update your workload-data. When finished you can download the upgraded data with the /EtimUp/GetUpgradedWorkload/{workloadId}.

The services are authorized via the OAuth2 protocol. Before using the webservices you have to get a client_id/client_secret from ETIM International.

You can find a lot of information about the OAuth2 protocol on the internet. Overal information about OAuth2 can be found here.
The webservices need an access_token in the Authorization Header of the request.
Authorization: Bearer {access_token}
The first time you have to get the access_token together with a refresh_token via the "Authorization Code Flow". After that you can refresh access roken via the refresh token.

Authorization Code Flow

For requiring an access_token you can use the OAuth2 "Authorization Code Flow".

  • The application opens an (embedded) browser and navigates to the ETIM authorization server (https://auth.ketenstandaard.nl/). This request contains the following parameters:
    https://auth.ketenstandaard.nl/connect/Authorize?response_type=code&scope={scope}&client_id={client_id}&redirect_uri={redirect_uri}
    • scope: EtimApi offline_access
    • client_id: Your client_id you got from Ketenstandaard.nl
    • redirect_uri: The url you want the ETIM authorization server to redirect to after authentication succeeded.
    var url = new Uri(string.Format("{0}/connect/Authorize?response_type=code&scope=EtimApi offline_access&client_id={1}&redirect_uri={0}", 
        Properties.Settings.Default.AuthorizeUrl, 
        Globals.ClientId));
    this.WebBrowser1.Navigate(url);
    
  • The user enters his/her credentials using the login page.
  • Navigation returns to the URL specified by redirect_uri with the parameter ?code={authorization_code}.
    private void WebBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
        //Look for the authorization code field
        const string SearchCondition = "/?code=";
        if (e.Url.PathAndQuery.StartsWith(SearchCondition))
        {
            var queryString = string.Join(string.Empty, e.Url.AbsoluteUri.Split('?').Skip(1));
            var parsedQuery = HttpUtility.ParseQueryString(queryString);
     
            this.Authorization_Code = parsedQuery["code"];
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
    }
    
  • The token service (see below) can then be invoked with a grant_type of "authorization_code" and the 'code' parameter set to the autorization code retrieved earlier:
    https://auth.ketenstandaard.nl/connect/Token/grant_type=authorization_code&code={0}&client_id={2}&client_secret={3}&redirect_uri={1}
    public static OAuthTokenResponse GetAccessToken(string authorizationCode)
    {
        var postMessage = string.Format("grant_type=authorization_code&code={0}&client_id={2}&client_secret={3}&redirect_uri={1}", 
            authorizationCode, 
            Settings.Default.AuthorizeUrl, 
            Globals.ClientId, 
            Globals.ClientSecret);
     
     
        var request = (HttpWebRequest)WebRequest.Create(Settings.Default.AuthorizeUrl + "/connect/Token");
     
        var data = Encoding.ASCII.GetBytes(postMessage);
     
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = data.Length;
     
     
        using (var stream = request.GetRequestStream())
        {
            stream.Write(data, 0, data.Length);
        }
    }
    								
  • The token service returns the access_token, refresh_token, lifetime etc. which can then be used to invoke the ETIM webservices:
    	var response = (HttpWebResponse)request.GetResponse();
        var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
     
        var token = new OAuthTokenResponse();
        var jobj = JObject.Parse(responseString);
        token.AccessToken = (string)jobj["access_token"];
        token.RefreshToken = (string)jobj["refresh_token"];
        token.ExpiresIn = (int)jobj["expires_in"];
        token.TokenGet = DateTime.Now;
        return token;
    

Token example

Token example.

public static class TokenServiceEtim
	{
		public static OAuthTokenResponse GetAccessToken(string authorizationCode)
		{
			// Get Access Token
			var postData = string.Format(
                "grant_type=authorization_code&code={0}&client_id={2}&client_secret={3}&redirect_uri={1}",
				authorizationCode,
				Settings.Default.RedirectUrl,
				Settings.Default.ClientIdEtim,
				Settings.Default.ClientSecretEtim);

			return Get(postData);
		}

		public static OAuthTokenResponse Renew(string refreshToken)
		{
			try
			{
				// Renew Accesstoken
				var postData = string.Format(
					"grant_type=refresh_token&client_id={0}&client_secret={1}&refresh_token={2}",
					Settings.Default.ClientIdEtim,
					Settings.Default.ClientSecretEtim,
					refreshToken);

				return Get(postData);
			}
			catch (WebException)
			{
				MessageBox.Show(Resources.Error_AuthTokenNotRenewed, "ETIM", MessageBoxButton.OK, MessageBoxImage.Error);
				return null;
			}
		}

		private static OAuthTokenResponse Get(string postMessage)
		{
			// Create Object's
			var request = (HttpWebRequest)WebRequest.Create(Settings.Default.AuthorizeEtimUrl + "/connect/Token");

			// Set request data
			var data = Encoding.UTF8.GetBytes(postMessage);

			// Set request method, contentType and contentLength
			request.Method = "POST";
			request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
			request.ContentLength = data.Length;

			using (var stream = request.GetRequestStream())
			{
				stream.Write(data, 0, data.Length);
			}

			// Get response
			var response = (HttpWebResponse)request.GetResponse();
			var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

			// Save response
			var token = JsonConvert.DeserializeObject(responseString);
			token.TokenGet = DateTime.Now;

			return token;
		}
	}

Webservices example

Webservices example.

	public class WorkloadService
	{
        private readonly HttpClient Client = new HttpClient();
        private Uri GetBaseUrl() => new Uri(Settings.Default.ApiEtimUrl);

        public WorkloadService()
		{
            Client.MaxResponseContentBufferSize = 256000;
            Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Settings.Default.TokenEtim.AccessToken);
        }

        public async Task UploadProductsAsync(List products)
		{
			var resultstring = await HttpPost($"/EtimUp/NewWorkload", products);
			
			return resultstring;
		}

        private async Task HttpPost(string relativeUrl, object data)
        {
            string content = null;
            var uri = new Uri(GetBaseUrl(), relativeUrl);

            var json = JsonConvert.SerializeObject(data, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

            var requestContent = new StringContent(json, Encoding.UTF8, "application/json");

            HttpResponseMessage response = null;
            response = await Client.PostAsync(uri, requestContent);

            if (response.IsSuccessStatusCode)
            {
                content = await response.Content.ReadAsStringAsync();
            }
            else if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
				// Did you refresh your access_token in time??
            }
            else
            {
                throw new Exception($"Error while posting message to {uri}. Statuscode: {response.StatusCode} Content: {response.Content}");
            }
            return content;
        }
    }