Skip to content

Commit adaf791

Browse files
committed
Adding C# Non-interactive (cert) login sample
1 parent c2b2bd3 commit adaf791

File tree

10 files changed

+354
-0
lines changed

10 files changed

+354
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Express 2013 for Windows Desktop
4+
VisualStudioVersion = 12.0.30723.0
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Betfair-Non-interactive-login", "Betfair-Non-interactive-login\Betfair-Non-interactive-login.csproj", "{EC79B231-1A08-42BC-8C1E-7D21FA849DAC}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{EC79B231-1A08-42BC-8C1E-7D21FA849DAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{EC79B231-1A08-42BC-8C1E-7D21FA849DAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{EC79B231-1A08-42BC-8C1E-7D21FA849DAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{EC79B231-1A08-42BC-8C1E-7D21FA849DAC}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
EndGlobal
Binary file not shown.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
5+
</startup>
6+
</configuration>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Security.Cryptography;
7+
using System.Security.Cryptography.X509Certificates;
8+
using System.Net.Http;
9+
using System.Net.Http.Headers;
10+
using System.Runtime.Serialization;
11+
using System.Runtime.Serialization.Json;
12+
using System.IO;
13+
14+
using Betfair_Non_interactive_login.Models;
15+
16+
namespace Betfair_Non_interactive_login
17+
{
18+
class AuthClient
19+
{
20+
21+
private string appKey;
22+
23+
public string AppKey
24+
{
25+
get { return appKey; }
26+
}
27+
28+
private WebRequestHandler getWebRequestHandlerWithCert (string certFilename)
29+
{
30+
var cert = new X509Certificate2(certFilename, "");
31+
var clientHandler = new WebRequestHandler();
32+
clientHandler.ClientCertificates.Add(cert);
33+
return clientHandler;
34+
}
35+
36+
private const string DEFAULT_COM_BASEURL = "https://identitysso.betfair.com";
37+
38+
private HttpClient initHttpClientInstance (WebRequestHandler clientHandler, string appKey, string baseUrl = DEFAULT_COM_BASEURL)
39+
{
40+
var client = new HttpClient(clientHandler);
41+
client.BaseAddress = new Uri(baseUrl);
42+
client.DefaultRequestHeaders.Accept.Clear();
43+
client.DefaultRequestHeaders.Add("X-Application", appKey);
44+
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
45+
return client;
46+
}
47+
48+
private FormUrlEncodedContent getLoginBodyAsContent (string username, string password)
49+
{
50+
var postData = new List<KeyValuePair<string, string>>();
51+
postData.Add(new KeyValuePair<string, string>("username", username));
52+
postData.Add(new KeyValuePair<string, string>("password", password));
53+
return new FormUrlEncodedContent(postData);
54+
}
55+
56+
public LoginResponse doLogin (string username, string password, string certFilename)
57+
{
58+
var handler = getWebRequestHandlerWithCert(certFilename);
59+
var client = initHttpClientInstance(handler, appKey);
60+
var content = getLoginBodyAsContent(username, password);
61+
var result = client.PostAsync("/api/certlogin", content).Result;
62+
result.EnsureSuccessStatusCode();
63+
var jsonSerialiser = new DataContractJsonSerializer(typeof(LoginResponse));
64+
var stream = new MemoryStream(result.Content.ReadAsByteArrayAsync().Result);
65+
return (LoginResponse)jsonSerialiser.ReadObject(stream);
66+
67+
}
68+
69+
public AuthClient (string appKey)
70+
{
71+
this.appKey = appKey;
72+
}
73+
}
74+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{EC79B231-1A08-42BC-8C1E-7D21FA849DAC}</ProjectGuid>
8+
<OutputType>Exe</OutputType>
9+
<AppDesignerFolder>Properties</AppDesignerFolder>
10+
<RootNamespace>Betfair_Non_interactive_login</RootNamespace>
11+
<AssemblyName>Betfair-Non-interactive-login</AssemblyName>
12+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13+
<FileAlignment>512</FileAlignment>
14+
</PropertyGroup>
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16+
<PlatformTarget>AnyCPU</PlatformTarget>
17+
<DebugSymbols>true</DebugSymbols>
18+
<DebugType>full</DebugType>
19+
<Optimize>false</Optimize>
20+
<OutputPath>bin\Debug\</OutputPath>
21+
<DefineConstants>DEBUG;TRACE</DefineConstants>
22+
<ErrorReport>prompt</ErrorReport>
23+
<WarningLevel>4</WarningLevel>
24+
</PropertyGroup>
25+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26+
<PlatformTarget>AnyCPU</PlatformTarget>
27+
<DebugType>pdbonly</DebugType>
28+
<Optimize>true</Optimize>
29+
<OutputPath>bin\Release\</OutputPath>
30+
<DefineConstants>TRACE</DefineConstants>
31+
<ErrorReport>prompt</ErrorReport>
32+
<WarningLevel>4</WarningLevel>
33+
</PropertyGroup>
34+
<ItemGroup>
35+
<Reference Include="System" />
36+
<Reference Include="System.Core" />
37+
<Reference Include="System.Net.Http" />
38+
<Reference Include="System.Net.Http.WebRequest" />
39+
<Reference Include="System.Runtime.Serialization" />
40+
<Reference Include="System.Security" />
41+
<Reference Include="System.Xml.Linq" />
42+
<Reference Include="System.Data.DataSetExtensions" />
43+
<Reference Include="Microsoft.CSharp" />
44+
<Reference Include="System.Data" />
45+
<Reference Include="System.Xml" />
46+
</ItemGroup>
47+
<ItemGroup>
48+
<Compile Include="AuthClient.cs" />
49+
<Compile Include="Models\KeepAliveLogoutResponse.cs" />
50+
<Compile Include="Models\LoginResponse.cs" />
51+
<Compile Include="Program.cs" />
52+
<Compile Include="Properties\AssemblyInfo.cs" />
53+
</ItemGroup>
54+
<ItemGroup>
55+
<None Include="App.config" />
56+
</ItemGroup>
57+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
58+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
59+
Other similar extension points exist, see Microsoft.Common.targets.
60+
<Target Name="BeforeBuild">
61+
</Target>
62+
<Target Name="AfterBuild">
63+
</Target>
64+
-->
65+
</Project>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Runtime.Serialization;
3+
using System.Runtime.Serialization.Json;
4+
5+
namespace Betfair_Non_interactive_login.Models
6+
{
7+
[DataContract]
8+
class KeepAliveLogoutResponse
9+
{
10+
[DataMember(Name = "token")]
11+
public string Token { get; set; }
12+
[DataMember(Name = "product")]
13+
public string Product { get; set; }
14+
[DataMember(Name = "status")]
15+
public string Status { get; set; }
16+
[DataMember(Name = "error")]
17+
public string Error { get; set; }
18+
}
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Runtime.Serialization;
3+
using System.Runtime.Serialization.Json;
4+
5+
namespace Betfair_Non_interactive_login.Models
6+
{
7+
[DataContract]
8+
public class LoginResponse
9+
{
10+
[DataMember(Name = "sessionToken")]
11+
public string SessionToken { get; set; }
12+
[DataMember(Name = "loginStatus")]
13+
public string LoginStatus { get; set; }
14+
}
15+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net;
5+
using System.Net.Http;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using System.Security.Cryptography;
9+
using System.Security.Cryptography.X509Certificates;
10+
11+
using System.Runtime.Serialization;
12+
using System.Runtime.Serialization.Json;
13+
using System.IO;
14+
using System.Net.Http.Headers;
15+
using System.Security;
16+
17+
using Betfair_Non_interactive_login.Models;
18+
19+
namespace Betfair_Non_interactive_login
20+
{
21+
class Program
22+
{
23+
static string getPassword()
24+
{
25+
string pass = "";
26+
ConsoleKeyInfo key;
27+
28+
do
29+
{
30+
key = Console.ReadKey(true);
31+
if (key.Key != ConsoleKey.Backspace && key.Key != ConsoleKey.Enter)
32+
{
33+
pass += key.KeyChar;
34+
Console.Write("*");
35+
}
36+
else
37+
{
38+
if (key.Key == ConsoleKey.Backspace && pass.Length > 0)
39+
{
40+
pass = pass.Substring(0, (pass.Length - 1));
41+
Console.Write("\b \b");
42+
}
43+
}
44+
}
45+
while (key.Key != ConsoleKey.Enter);
46+
47+
return pass;
48+
}
49+
50+
static void Main(string[] args)
51+
{
52+
if (args.Count() != 3)
53+
{
54+
Console.WriteLine("This sample takes 3 arguments: <username> <appkey> <pathtocertfile>");
55+
Console.WriteLine("You will then be prompted for the password for this account.");
56+
}
57+
else
58+
{
59+
var username = args.First();
60+
var appKey = args.ElementAt(1);
61+
var certFilename = args.ElementAt(2);
62+
Console.WriteLine("Please enter your password:");
63+
var password = Program.getPassword();
64+
Console.WriteLine("");
65+
66+
var client = new AuthClient(appKey);
67+
try
68+
{
69+
var resp = client.doLogin(username, password, certFilename);
70+
Console.WriteLine("Response Type: " + resp.LoginStatus);
71+
if (resp.LoginStatus == "SUCCESS")
72+
{
73+
Console.WriteLine("Obtained the session token: " + resp.SessionToken);
74+
}
75+
}
76+
catch (CryptographicException e)
77+
{
78+
Console.WriteLine("Could not load the certificate: " + e.Message);
79+
}
80+
catch (HttpRequestException e)
81+
{
82+
Console.WriteLine("The Betfair Login endpoint returned an HTTP Error: " + e.Message);
83+
}
84+
catch (WebException e)
85+
{
86+
Console.WriteLine("An error occurred whilst attempting to make the request: " + e.Message);
87+
}
88+
catch (Exception e)
89+
{
90+
Console.WriteLine("An Error Occurred: " + e.Message);
91+
}
92+
}
93+
}
94+
}
95+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("Betfair-Non-interactive-login")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("Betfair")]
12+
[assembly: AssemblyProduct("Betfair-Non-interactive-login")]
13+
[assembly: AssemblyCopyright("Copyright © Betfair 2014")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("d40933c3-826d-4b57-a386-62d0d2bd4c0a")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Betfair API-NG C# Non-interactive login example
2+
This project provides example usage of requests to Betfair's [Non-interactive Login](https://api.developer.betfair.com/services/webapps/docs/display/1smk3cen4v3lu3yomq5qye0ni/Non-Interactive+%28bot%29+login). You should read the guide and create yourself a key prior to using this sample.
3+
4+
## Running instructions
5+
You need to convert your key to a format that the .NET Platform understands, a [PKCS12 File](http://en.wikipedia.org/wiki/PKCS_12).
6+
```shell
7+
openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -out certificate.pfx
8+
```
9+
When asked to provide a password, leave the passphrase blank or you will need to update the sample file where the X509Certificate2 is instantiated in order to provide the passphrase.
10+
11+
Once you have made sure that your key is uploaded to the Betfair My Account -> My Security page following the instructions in the introduction above, you can invoke the sample as follows.
12+
13+
* Open up Visual Studio or Visual Studio Express and build the app once by pressing F7.
14+
* Open up the windows command line (cmd.exe) in the right place by holding Shift and Right clicking on the Debug directory within the "bin" folder in this project and select "Open Command Window here".
15+
* Run the tool by executing :
16+
``shell
17+
Betfair-Non-Interactive-login.exe myUsername myAppKey "C:\Path to my\certificate.p12"
18+
```
19+
* You will be asked to enter your password.
20+
* You will then be provided a session token.
21+
22+
This sample takes 3 arguments: Betfair-Non-Interactive-login.exe {username} {appkey} {pathtocertfile}

0 commit comments

Comments
 (0)