Private key is not present in x509 - wcf

Why am I getting this exception. The private key is not present in x509 certificate
This is to generate a username with nonce+ 2 binary security tokens(one for the usercertificate and one for the server).
My user certificate has a private key but the server certificate does not have one.
This is for Asymmetric binding.
using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.Text;
namespace MYEmedny
{
public class CustomCredentials : ClientCredentials
{
private X509Certificate2 clientAuthCert;
private X509Certificate2 clientSigningCert;
public CustomCredentials() : base() { }
public CustomCredentials(CustomCredentials other)
: base(other)
{
// other.clientSigningCert = SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "LMWARD");
clientSigningCert = other.clientSigningCert;
clientAuthCert = other.clientAuthCert;
}
protected override ClientCredentials CloneCore()
{
CustomCredentials scc = new CustomCredentials(this);
return scc;
}
public CustomCredentials(X509Certificate2 ClientAuthCert, X509Certificate2 ClientSigningCert)
: base()
{
clientAuthCert = ClientAuthCert;
clientSigningCert = ClientSigningCert;
}
public X509Certificate2 ClientAuthCert
{
get { return clientAuthCert; }
set { clientAuthCert = value; }
}
public X509Certificate2 ClientSigningCert
{
get { return clientSigningCert; }
set { clientSigningCert = value; }
}
public override SecurityTokenManager CreateSecurityTokenManager()
{
return new CustomTokenManager(this);
}
}
public class CustomTokenManager : ClientCredentialsSecurityTokenManager
{
private CustomCredentials custCreds;
public CustomTokenManager(CustomCredentials CustCreds)
: base(CustCreds)
{
custCreds = CustCreds;
}
public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
{
try
{
if (tokenRequirement.TokenType == SecurityTokenTypes.X509Certificate)
{
x509CustomSecurityTokenProvider prov;
object temp = null;
//TransportSecurityBindingElement secBE = null;
AsymmetricSecurityBindingElement secBE = null;
if (tokenRequirement.Properties.TryGetValue("http://schemas.microsoft.com/ws/2006/05/servicemodel/securitytokenrequirement/SecurityBindingElement", out temp))
{
//secBE = (TransportSecurityBindingElement)temp;
secBE = (AsymmetricSecurityBindingElement)temp;
}
if (secBE == null)
prov = new x509CustomSecurityTokenProvider(custCreds.ClientAuthCert);
else
prov = new x509CustomSecurityTokenProvider(custCreds.ClientSigningCert);
return prov;
}
}
catch (Exception ex)
{
throw ex;
}
return base.CreateSecurityTokenProvider(tokenRequirement);
}
public override System.IdentityModel.Selectors.SecurityTokenSerializer CreateSecurityTokenSerializer(System.IdentityModel.Selectors.SecurityTokenVersion version)
{
return new CustomTokenSerializer(System.ServiceModel.Security.SecurityVersion.WSSecurity10);
}
}
class x509CustomSecurityTokenProvider : SecurityTokenProvider
{
private X509Certificate2 clientCert;
public x509CustomSecurityTokenProvider(X509Certificate2 cert)
: base()
{
clientCert = cert;
}
protected override SecurityToken GetTokenCore(TimeSpan timeout)
{
return new X509SecurityToken(clientCert);
}
}
public class CustomTokenSerializer : WSSecurityTokenSerializer
{
public CustomTokenSerializer(SecurityVersion sv) : base(sv) { }
protected override void WriteTokenCore(System.Xml.XmlWriter writer, System.IdentityModel.Tokens.SecurityToken token)
{
if (writer == null)
{
throw new ArgumentNullException("writer");
}
if (token == null)
{
throw new ArgumentNullException("token");
}
if (token.GetType() == new UserNameSecurityToken("x", "y").GetType())
{
UserNameSecurityToken userToken = token as UserNameSecurityToken;
if (userToken == null)
{
throw new ArgumentNullException("userToken: " + token.ToString());
}
string tokennamespace = "wsse";
DateTime created = DateTime.Now;
string createdStr = created.ToString("yyyy-MM-ddThh:mm:ss.fffZ");
string phrase = Guid.NewGuid().ToString();
string nonce = GetSHA1String(phrase);
string password = userToken.Password;
//string password = userToken.Password;
writer.WriteStartElement(tokennamespace, "UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
writer.WriteAttributeString("wsu", "Id", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", token.Id);
writer.WriteElementString(tokennamespace, "Username", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", userToken.UserName);
writer.WriteStartElement(tokennamespace, "Password", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
writer.WriteValue(password);
writer.WriteEndElement();
writer.WriteStartElement(tokennamespace, "Nonce", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
writer.WriteAttributeString("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
writer.WriteValue(nonce);
writer.WriteEndElement();
writer.WriteElementString(tokennamespace, "Created", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", createdStr);
writer.WriteEndElement();
writer.Flush();
}
else
{
base.WriteTokenCore(writer, token);
}
}
protected string GetSHA1String(string phrase)
{
SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
byte[] hashedDataBytes = sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase));
return Convert.ToBase64String(hashedDataBytes);
}
}//CustomTokenSerializer
}
This is how I am using it
private CustomBinding GetCustomBinding()
{
AsymmetricSecurityBindingElement secBE = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement
(
MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10
);
secBE.ProtectTokens = false;
X509SecurityTokenParameters x509ProtectionParameters = new X509SecurityTokenParameters();
x509ProtectionParameters.RequireDerivedKeys = false;
x509ProtectionParameters.X509ReferenceStyle = X509KeyIdentifierClauseType.SubjectKeyIdentifier;
x509ProtectionParameters.ReferenceStyle = SecurityTokenReferenceStyle.Internal;
//x509ProtectionParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
secBE.MessageSecurityVersion = System.ServiceModel.MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
secBE.InitiatorTokenParameters = x509ProtectionParameters;
secBE.RecipientTokenParameters = x509ProtectionParameters;
secBE.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;
secBE.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
secBE.EnableUnsecuredResponse = true;
secBE.SetKeyDerivation(false);
secBE.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.TripleDesRsa15;
secBE.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters());
secBE.ProtectTokens = true;
// secBE.in = SecurityTokenInclusionMode.Never, RequireDerivedKeys = false );
secBE.EnableUnsecuredResponse = true;
secBE.IncludeTimestamp = false;
TextMessageEncodingBindingElement textEncBE = new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, System.Text.Encoding.UTF8);
HttpsTransportBindingElement httpsBE = new HttpsTransportBindingElement();
httpsBE.RequireClientCertificate = true;
CustomBinding myBinding = new CustomBinding();
myBinding.Elements.Add(secBE);
myBinding.Elements.Add(textEncBE);
myBinding.Elements.Add(httpsBE);
return myBinding;
}
ProxyGeneration.MHSClient proxy = new ProxyGeneration.MHSClient(GetCustomBinding(), new EndpointAddress(new Uri("https://service100.emedny.org:9047/MHService"), EndpointIdentity.CreateDnsIdentity("DPMedsHistory"), new AddressHeaderCollection()));
var vs = proxy.Endpoint.Behaviors.Where((i) => i.GetType().Namespace.Contains("VisualStudio"));
proxy.Endpoint.Behaviors.Remove((System.ServiceModel.Description.IEndpointBehavior)vs.Single());
proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName,"User");
proxy.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "Server");
proxy.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
proxy.Endpoint.Behaviors.Add(new CustomCredentials(GetCertificateFromStore("User"), GetCertificateFromStore("Server")));
proxy.ClientCredentials.UserName.UserName = "User1";
proxy.ClientCredentials.UserName.Password = "PWD";

Related

HttpClient does not work with dev certifcate

I want to use HttpClient to make requests using a certificate.
I generated a dev certificate using the following command
dotnet dev-certs https -ep dev_cert.pfx -p 1234
So I created an API to use that certificate. Here is the implementation.
public static class AuthenticationExtension
{
public static void ConfigureAuthetication(this IServiceCollection services)
{
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
var cert = new X509Certificate2(#"D:\dev_cert.pfx", "1234");
options.AllowedCertificateTypes = CertificateTypes.All;
options.ChainTrustValidationMode = X509ChainTrustMode.CustomRootTrust;
options.CustomTrustStore = new X509Certificate2Collection { cert };
options.RevocationMode = X509RevocationMode.NoCheck;
options.ValidateCertificateUse = false;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var validationService = context.HttpContext.RequestServices.GetService<ClientCertificateValidationService>();
if (validationService != null && validationService.ValidateCertificate(context.ClientCertificate))
{
Console.WriteLine("Success");
context.Success();
}
else
{
Console.WriteLine("invalid cert");
context.Fail("invalid cert");
}
return Task.CompletedTask;
},
OnChallenge = context =>
{
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
Console.WriteLine("Failed");
return Task.CompletedTask;
}
};
});
services.AddAuthorization();
}
}
I added the Authorize attribute in the controller method
[HttpGet(Name = "GetWeatherForecast")]
[Authorize]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
I tested the request using Postman and it worked as expected.
Then, I created a console app to make the request using HttpClient. It failed always with the Forbidden Status code.
So I tested using the obsolete WebRequest. And It worked as expected.
Here is the implementation for that
using System.Net;
using System.Security.Cryptography.X509Certificates;
var handler = new HttpClientHandler();
X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(#"D:\dev_cert.pfx", "1234", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
handler.ClientCertificates.AddRange(certificates);
using var client = new HttpClient(handler);
client.BaseAddress = new Uri("https://localhost:7148/");
try
{
var response = await client.GetAsync("weatherforecast/");
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
else
{
Console.WriteLine($"Failed {response.StatusCode}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed {ex}");
}
string host = #"https://localhost:7148/weatherforecast";
try
{
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(host);
req.AllowAutoRedirect = true;
req.ClientCertificates = certificates;
req.Method = "GET";
WebResponse resp = req.GetResponse();
Stream stream = resp.GetResponseStream();
using (StreamReader reader = new StreamReader(stream))
{
string line = reader.ReadLine();
while (line != null)
{
Console.WriteLine(line);
line = reader.ReadLine();
}
}
stream.Close();
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
My question is... Since the WebRequest is obsolete what I can do to make the HttpClient work?
Thank you in Advance!

How do i get data from Rest API

Please, i am trying to access data from rest API,
From the Documentation ,to get the token, i have to make a post call ,then use the token received to access two other results:
for the token, they gave this from the documentation:
https://apps.qa.interswitchng.com/passport/oauth/token
with the following Query Params
grant_type string
Headers
Authorization string required
Set value to "Basic Base64(CLIENT_ID:SECRET_KEY)"
Content-Type application/x-www-form-urlencoded
string
My Codes
#SuppressLint("StaticFieldLeak")
class SendTokenReqAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage("processing Token");
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected String doInBackground(String... params) {
JSONObject jsonObject2 = new JSONObject();
InputStream inputStream = null;
String result2 = "";
base64EncodedCredentials = "Basic" + Base64.encodeToString ((CLIENT_ID + ":" + SECRET) .getBytes (), Base64.NO_WRAP);
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(" https://apps.qa.interswitchng.com/passport/oauth/token/");
//StringEntity stringEntity2 = new StringEntity(userPhoneNumber);
//httpPost.setEntity(stringEntity2);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Authorization", base64EncodedCredentials);
httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
HttpResponse httpResponse1 = httpclient.execute(httpPost);
inputStream = httpResponse1.getEntity().getContent();
InputStreamReader inputStreamReader1 = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader1);
StringBuilder stringBuilder2 = new StringBuilder();
String bufferedStrChunk = null;
int data = inputStreamReader1.read();
while((bufferedStrChunk = bufferedReader.readLine()) != null){
stringBuilder2.append(bufferedStrChunk);
}
result2=stringBuilder2.toString();
return result2;
} catch (Exception e) {
Log.d("InputStream", e.getLocalizedMessage());
}
return null;
}
#Override
protected void onPostExecute(String result2) {
super.onPostExecute(result2);
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setCancelable(true);
progressDialog.hide();
//String re=null;
/*try {
JSONObject jsonObject = new JSONObject(result2);
re = jsonObject.getString(result2);
} catch (JSONException e) {
e.printStackTrace();
}*/
txtInfo = findViewById(R.id.textViewMain);
txtInfo.setVisibility(View.VISIBLE);
txtInfo.setText(MessageFormat.format("Token is :{0}", result2));
}
}
with the below code in the oncreate
SendTokenReqAsyncTask myAsyncTasks = new SendTokenReqAsyncTask();
myAsyncTasks.execute();
i also used retrofit this way
#SuppressWarnings("deprecation")
public class MyRetrofitClient {
protected static MyRetrofitClient myRetrofitClient = null;
private static RetroApis myRetroApis;
private static TokenAPI tokenAPI;
private static Retrofit retrofit = null;
private String tokenFromServer;
String clientID,secret;
private byte[] data64;
String base64=null;
MyRetrofitClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(TOKEN_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
myRetroApis = retrofit.create(RetroApis.class);
}
public String encodeToBase64() {
clientID= CLIENT_ID1;
secret=SECRET1;
String text = clientID + ":" + secret;
data64 = new byte[0];
data64 = text.getBytes(StandardCharsets.UTF_8);
base64=android.util.Base64.encodeToString(data64, android.util.Base64.DEFAULT);
return base64;
}
static Retrofit getTokenClient() {
String type="application/x-www-form-urlencoded";
String base64String=MyRetrofitClient.myRetrofitClient.encodeToBase64();
RequestBody requestBody = RequestBody.create(MediaType.parse("Content-type"), type);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
logging.redactHeader("Authorization");
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(logging)
.addNetworkInterceptor(new Interceptor() {
#NotNull
#Override
public Response intercept(#NotNull Interceptor.Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("Authorization", MyRetrofitClient.getInstance().encodeToBase64()).build();
return chain.proceed(request);
}
})
.addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
.build();
retrofit = new Retrofit.Builder()
.baseUrl(TOKEN_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
return retrofit;
}
static Retrofit getTCreditReportClient(String tokenFromServer,String userPhoneNumber) {
String type="application/json";
RequestBody requestBody = RequestBody.create(MediaType.parse("Content-type"), type);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
//logging.setLevel(HttpLoggingInterceptor.Level.BODY);
logging.redactHeader("Authorization");
logging.redactHeader("Content-type");
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(logging)
.addNetworkInterceptor(new Interceptor() {
#NotNull
#Override
public Response intercept(#NotNull Interceptor.Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("Authorization", tokenFromServer).build();
//Request request3 = chain.request().newBuilder().method("Content-type", requestBody).build();
return chain.proceed(request);
}
})
.addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
retrofit = new Retrofit.Builder()
.baseUrl("https://reqres.in")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
return retrofit;
}
static Retrofit getClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
//logging.setLevel(HttpLoggingInterceptor.Level.BODY);
logging.redactHeader("Authorization");
logging.redactHeader("Cookie");
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
retrofit = new Retrofit.Builder()
.baseUrl("https://reqres.in")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
public static synchronized MyRetrofitClient getInstance() {
if (myRetrofitClient == null) {
myRetrofitClient = new MyRetrofitClient();
}
return myRetrofitClient;
}
public RetroApis getMyApi() {
return myRetroApis;
}
public TokenAPI getMyTokenApi() {
return tokenAPI;
}
}
public interface TokenAPI {
String contentType= "application/json";
String authorization= "<>";
#FormUrlEncoded
#POST("client_credentials")
Call<OAuthToken> postCredentials(#Field("grant_type") String grantType);
//#FormUrlEncoded
#GET("creditScores")
Call<CreditScore> getCreditScore(#Query("client_credentials") String queryParam);
//#FormUrlEncoded
#GET("creditScores")
Call<List<CreditScoreHistory>> getCreditScoreHistory(#Query("client_credentials") String name);
#GET("/1.1/users/show.json")
Call<String> getUserDetails(#Query("screen_name") String name);
}
private void createInterSwitchTokenAPI33() {
editText = findViewById(R.id.editText);
base64EncodedCredentials = "Basic" + Base64.encodeToString ((CLIENT_ID + ":" + SECRET) .getBytes (), Base64.NO_WRAP);
//base64String=this.encodeToBase64();
String editTextInput = Objects.requireNonNull(editText.getText()).toString();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
logging.redactHeader("Authorization");
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(logging)
.addNetworkInterceptor(new Interceptor() {
#NotNull
#Override
public okhttp3.Response intercept(#NotNull Interceptor.Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("Authorization", base64EncodedCredentials).build();
return chain.proceed(request);
}
})
.addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(TOKEN_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
tokenAPI = retrofit.create(TokenAPI.class);
tokenAPI.getCreditScore(editTextInput).enqueue(creditScoreCallback);
}
public void onClick(View view) {
if (view.getId() == R.id.post) {
editText = findViewById(R.id.editText);
String editTextInput = editText.getText().toString();
if (!editTextInput.isEmpty())
createCreditScoreAPI(token);
createHistoryAPI(token);
tokenAPI.getCreditScore(editTextInput).enqueue(creditScoreCallback);
tokenAPI.getCreditScoreHistory(editTextInput).enqueue(creditScoreHistoryCallback);
} else {
Toast.makeText(this, "Please provide your BVN Phone Number", Toast.LENGTH_LONG).show();
}
}
private void createCreditScoreAPI(OAuthToken token) {
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#NotNull
#Override
public okhttp3.Response intercept(#NotNull Chain chain) throws IOException {
//Request originalRequest = chain.request();
Request request = chain.request().newBuilder().addHeader("Authorization", token.getAccessToken()).build();
return chain.proceed(request);
}
}).addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS))
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(SCORE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
tokenAPI = retrofit.create(TokenAPI.class);
}
Callback<CreditScore> creditScoreCallback = new Callback<CreditScore>() {
#Override
public void onResponse(Call<CreditScore> call, Response<CreditScore> response) {
if (response.isSuccessful()) {
CreditScore creditScore = response.body();
if (creditScore != null) {
id = creditScore.getId();
msisdn = creditScore.getMsisdn();
score = creditScore.getScore();
dateCreated = creditScore.getDateCreated();
}
displayResponse += id + " Phone\n" + msisdn + " Score\n" + score + " dateCreated\n"+dateCreated;
txtCreditScore = findViewById(R.id.textCreditScore);
if (displayResponse == null) txtCreditScore.setText("no value");
else txtCreditScore.setText(displayResponse);
} else {
Toast.makeText(MainActivity.this, "Failure while requesting Credit Score", Toast.LENGTH_LONG).show();
txtCreditScore.setText(MessageFormat.format("Error!{0}", response.message()));
Log.d("Credit Score Details", "Code: " + response.code() + "Message: " + response.message());
}
}
#Override
public void onFailure(Call<CreditScore> call, Throwable t) {
t.printStackTrace();
}
};
private void createHistoryAPI(OAuthToken token) {
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#NotNull
#Override
public okhttp3.Response intercept(#NotNull Chain chain) throws IOException {
Request originalRequest = chain.request();
Request request = chain.request().newBuilder().addHeader("Authorization", token.getAccessToken()).build();
return chain.proceed(request);
}
}).addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS))
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(HISTORY_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
tokenAPI = retrofit.create(TokenAPI.class);
}
Callback<List<CreditScoreHistory>> creditScoreHistoryCallback = new Callback<List<CreditScoreHistory>>() {
#Override
public void onResponse(Call<List<CreditScoreHistory>> call, Response<List<CreditScoreHistory>> response) {
if (response.isSuccessful()) {
recyclerView = findViewById(R.id.recyclerViewHistory);
} else {
Toast.makeText(MainActivity.this, "Failure while requesting user details", Toast.LENGTH_LONG).show();
Log.d("History Callback", "Code: " + response.code() + "Message: " + response.message());
}
if (response.isSuccessful()) {
CreditScoreHistory creditScoreHistory = new CreditScoreHistory();
creditScoreList = response.body();
if (creditScoreList != null) {
for (int i = 0; i < creditScoreList.size(); i++) {
creditScoreList.add(creditScoreHistory);
count=creditScoreList.size();
}
if(creditScoreHistory !=null){
msisdn = creditScoreHistory.getMsisdn1();
score = creditScoreHistory.getScore1();
dateCreated = creditScoreHistory.getDateCreated1();
creditScoreList = creditScoreHistory.data;
}
}
displayResponse += count+" Phone\n" + msisdn + " Score\n" + score + " dateCreated\n"+dateCreated;
txtCreditHistory = findViewById(R.id.textCreditHistory);
creditHistoryAdapter = new CreditHistoryAdapter(MainActivity.this, creditScoreList);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(creditHistoryAdapter);
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
recyclerView.setNestedScrollingEnabled(false);
if (displayResponse == null) txtCreditScore.setText("no value");
else txtCreditHistory.setText(displayResponse);
} else {
Toast.makeText(MainActivity.this, "Failure while requesting Credit Score", Toast.LENGTH_LONG).show();
txtCreditHistory.setText(MessageFormat.format("Error!{0}", response.message()));
Log.d("Credit Score History", "Code: " + response.code() + "Message: " + response.message());
}
}
#Override
public void onFailure(Call<List<CreditScoreHistory>> call, Throwable t) {
t.printStackTrace();
}
};
buy could not get any result, please help
Use VSCode and ThunderClient extension https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client

Why is WCF service not invoke when security is enabled on Async operations

When Security feature is enabled for Authencation using X509 certificate, Connecation to the server is not established. I find this issue when the client makes Async operation call. The code below works for synchronous operation. For instance if the call is made TrainHealth instead of BeginTrainHealth, the code works fine. As I understand, security is independent of whether operations are sync or async.
Any help on why this is not working is appreciated.
Contract :
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.bane.dk/services/fbane/2014/02/20", ConfigurationName = "Alstom.SmartBus.ESBBridge.ExternalIOPlugins.TrainData.TrainDataPort")]
public interface IStudentService
{
[System.ServiceModel.OperationContractAttribute(IsOneWay = true, AsyncPattern = false, Action = "TrainHealth")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
void TrainHealth(int test);
[System.ServiceModel.OperationContractAttribute(IsOneWay = true, AsyncPattern = true, Action = "TrainHealth")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
System.IAsyncResult BeginTrainHealth(int test, System.AsyncCallback callback, object asyncState);
void EndTrainHealth(System.IAsyncResult result);
}
Server Code :
class Program
{
static void Main(string[] args)
{
ServiceHost studentServiceHost = null;
try
{
//Base Address for StudentService
Uri httpBaseAddress = new Uri("https://10.107.64.33:5060/StudentService");
//Instantiate ServiceHost
studentServiceHost = new ServiceHost(typeof(StudentService), httpBaseAddress);
CustomBinding binding = CreateBinding();
ServiceEndpoint endpoint_GD = studentServiceHost.AddServiceEndpoint(typeof(IStudentService), binding, httpBaseAddress);
//Add Endpoint to Host
studentServiceHost.AddServiceEndpoint(typeof(IStudentService), binding, httpBaseAddress + "mex");
//Metadata Exchange
ServiceMetadataBehavior serviceBehavior = new ServiceMetadataBehavior();
serviceBehavior.HttpsGetEnabled = true;
studentServiceHost.Description.Behaviors.Add(serviceBehavior);
var behavior = studentServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
behavior.IncludeExceptionDetailInFaults = true;
studentServiceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
studentServiceHost.Credentials.ClientCertificate.Authentication.TrustedStoreLocation = StoreLocation.LocalMachine;
studentServiceHost.Credentials.ServiceCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName, "10.107.64.33");
ServiceSecurityAuditBehavior newAudit = new ServiceSecurityAuditBehavior();
newAudit.AuditLogLocation = AuditLogLocation.Application;
newAudit.MessageAuthenticationAuditLevel = AuditLevel.SuccessOrFailure;
newAudit.ServiceAuthorizationAuditLevel = AuditLevel.SuccessOrFailure;
newAudit.SuppressAuditFailure = false;
studentServiceHost.Description.Behaviors.Remove<ServiceSecurityAuditBehavior>();
studentServiceHost.Description.Behaviors.Add(newAudit);
studentServiceHost.Open();
Console.WriteLine("Service is live now at : {0}", httpBaseAddress);
Console.ReadKey();
}
catch (Exception ex)
{
studentServiceHost = null;
Console.WriteLine("There is an issue with StudentService" + ex.Message);
Console.ReadKey();
}
}
public static CustomBinding CreateBinding()
{
CustomBinding binding = new CustomBinding();
binding.Elements.Add(new ReliableSessionBindingElement());
TransportSecurityBindingElement sec = new TransportSecurityBindingElement();
binding.Elements.Add(sec);
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, Encoding.UTF8));
binding.Elements.Add(new HttpsTransportBindingElement()
{
RequireClientCertificate = true
});
return binding;
}
}
Client Code :
class Program
{
static ChannelFactory<IStudentService> runTrainSvcCF = null;
static IStudentService runTrainSvcProxy;
static void Main(string[] args)
{
StartClient();
}
private static void StartClient()
{
EndpointAddress endPoint = new EndpointAddress(new Uri("https://10.107.64.33:5060/StudentService"), EndpointIdentity.CreateDnsIdentity("10.107.64.34"));
CustomBinding binding = CreateBinding();
runTrainSvcCF = new ChannelFactory<IStudentService>(binding, endPoint);
System.ServiceModel.Description.ClientCredentials credentials = runTrainSvcCF.Credentials;
credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser,
System.Security.Cryptography.X509Certificates.StoreName.My,
System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName,
"10.107.64.34");
ServicePointManager.MaxServicePointIdleTime = 0;
credentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(ValidateRemoteCertificate);
runTrainSvcProxy = runTrainSvcCF.CreateChannel();
try
{
runTrainSvcProxy.BeginTrainHealth(88, null, null);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static bool ValidateRemoteCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate cert,
System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors policyErrors)
{
return true;
}
public static CustomBinding CreateBinding()
{
CustomBinding binding = new CustomBinding();
binding.Elements.Add(new ReliableSessionBindingElement());
binding.Elements.Add(new TransportSecurityBindingElement());
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, Encoding.UTF8));
binding.Elements.Add(new HttpsTransportBindingElement()
{
RequireClientCertificate = true
});
return binding;
}
}

VCR for ServiceStack's JsonServiceClient

The Ruby VCR library enables you to "Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests."
I'd like to create something similar using ServiceStack's JsonServiceClient, but I can't get it to work. My most recent failed attempt follows. I'd like to either make my current attempt work, or suggestions on another approach that will work.
public static class Memoization
{
public static Func<T, TResult> AsCached<T, TResult>(this Func<T, TResult> function)
{
var cachedResults = new Dictionary<T, TResult>();
string filename = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + (typeof(TResult)).Name + ".jsv";
var serializer = MessagePackSerializer.Create<Dictionary<T, TResult>>();
if (cachedResults.Count == 0)
{
////// load cache from file
using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
cachedResults = serializer.Unpack(fs);
}
}
return (argument) =>
{
TResult result;
lock (cachedResults)
{
if (!cachedResults.TryGetValue(argument, out result))
{
result = function(argument);
cachedResults.Add(argument, result);
////// update cache file
using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
serializer.Pack(fs, cachedResults);
}
}
}
return result;
};
}
}
class MemoizeJsonClient<TResponse> : JsonServiceClient, IServiceClient, IRestClient
{
private Func<IReturn<TResponse>, TResponse> _getCached;
private JsonServiceClient client;
public TResponse Get(IReturn<TResponse> request)
{
if (_getCached == null)
{
Func<IReturn<TResponse>, TResponse> func = GetImpl;
_getCached = func.AsCached();
}
return _getCached(request);
}
private TResponse GetImpl(IReturn<TResponse> request)
{
return client.Get(request);
}
public MemoizeJsonClient(string BaseUri) {
client = new JsonServiceClient(BaseUri);
}
}
Called like this:
[Test]
public void TestReports2()
{
string Host = "http://localhost:1337";
string BaseUri = Host + "/";
List<Options> testcases = new List<Options>();
testcases.Add(new Options("Name", "20130815", "20130815"));
foreach (Options options in testcases)
{
TransactionsReq transRequest = new TransactionsReq();
transRequest.source = "Source";
transRequest.name = new List<String>(new string[] { options.Name });
transRequest.startDate = options.StartDate;
transRequest.endDate = options.EndDate;
MemoizeJsonClient<TransactionsReqResponse> client = new MemoizeJsonClient<TransactionsReqResponse>(BaseUri);
List<Transaction> transactions;
TransactionsReqResponse transResponse = client.Get(transRequest);
transactions = transResponse.data;
}
}
But I get the following error:
System.Runtime.Serialization.SerializationException occurred
HResult=-2146233076
Message=Cannot serialize type 'ServiceStack.ServiceHost.IReturn`1[ImagineServerWrapper.DTO.TransactionsReqResponse]' because it does not have any serializable fields nor properties.
Source=MsgPack
StackTrace:
at MsgPack.Serialization.SerializerBuilder`1.CreateSerializer()
InnerException:

Worklight Security WorkLightAuthLoginModule

I'm using the WorkLightAuthenticator to validate User login.
But I need to return some parameters like userName, organozationID, among others. What would be the correct way to return this data?
I believe that would be the method createIdentity as exemple down. And to retrieve the data on the client?
/*Worklight Adapter*/
public class LoginModule implements WorkLightAuthLoginModule {
private String USERNAME;
private String PASSWORD;
public void init(Map<String, String> options) throws MissingConfigurationOptionException {
}
#SuppressWarnings("unchecked")
public boolean login(Map<String, Object> authenticationData) {
USERNAME = (String) authenticationData.get("username");
PASSWORD = (String) authenticationData.get("password");
InvocationResult invocationResult = callLoginAdapter(USERNAME, PASSWORD);
JSONObject jsonObject = invocationResult.toJSON();
HashMap<String, String> result = (HashMap<String, String>) jsonObject.get("result");
if(result != null){
return true;
} else {
HashMap<String, String> fault = (HashMap<String, String>) jsonObject.get("Fault");
String detail = fault.get("Detail");
throw new RuntimeException(detail);
}
}
public UserIdentity createIdentity(String loginModule) {
HashMap<String, Object> customAttributes = new HashMap<String, Object>();
customAttributes.put("AuthenticationDate", new Date());
customAttributes.put("userName", userExample);
customAttributes.put("organizationID", 1);
UserIdentity identity = new UserIdentity(loginModule, USERNAME, null, null, customAttributes, PASSWORD);
return identity;
}
public void logout() {
USERNAME = null;
PASSWORD = null;
}
public void abort() {
USERNAME = null;
PASSWORD = null;
}
#Override
public LoginModule clone() throws CloneNotSupportedException {
return (LoginModule) super.clone();
}
public InvocationResult callLoginAdapter(String user, String password){
DataAccessService service = WorklightBundles.getInstance().getDataAccessService();
String parameters = "['"+user+"','"+password+"']";
ProcedureQName procedureQName = new ProcedureQName("LoginAdapter", "getUserByLogin");
return service.invokeProcedure(procedureQName, parameters);
}
}
And AuthenticatorRealmChallengeHandler in client-side
/*AuthenticatorRealmChallengeHandler.js*/
var customAuthenticatorRealmChallengeHandler = WL.Client.createChallengeHandler("AuthenticatorRealm");
customAuthenticatorRealmChallengeHandler.isCustomResponse = function(response) {
console.log("**********************");
console.log(response.responseJSON);
if (!response || !response.responseJSON) {
return false;
}
if (response.responseJSON.authStatus)
return true;
else
return false;
};
customAuthenticatorRealmChallengeHandler.handleChallenge = function(response){
var authStatus = response.responseJSON.authStatus;
if (authStatus == "required"){
if (response.responseJSON.errorMessage){
currentPage.loginFail(response.responseJSON.errorMessage);
}
} else if (authStatus == "complete"){
currentPage.loadMaster();
customAuthenticatorRealmChallengeHandler.submitSuccess();
}
};
customAuthenticatorRealmChallengeHandler.submitLoginFormCallback = function(response) {
var isLoginFormResponse = customAuthenticatorRealmChallengeHandler.isCustomResponse(response);
if (isLoginFormResponse){
customAuthenticatorRealmChallengeHandler.handleChallenge(response);
}
};
$('#loginButton').bind('click', function () {
var reqURL = '/auth_request_url';
var options = {};
options.parameters = {
username : $('#userTextField').val(),
password : $('#passwordTextField').val()
};
options.headers = {};
customAuthenticatorRealmChallengeHandler.submitLoginForm(reqURL, options, customAuthenticatorRealmChallengeHandler.submitLoginFormCallback);
});
var attributes = WL.Client.getUserInfo("AuthenticatorRealm", "attributes");