Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
f759dd8
Rename PairingStatus to Pairing
Feb 9, 2015
9db9440
Rename AuthenticationStatus to AuthenticationRequest
Feb 9, 2015
e4492ac
Update ToopherApi.Pair to handle regular pairing, QR pairing and SMS …
Feb 9, 2015
3ee9249
Update ToopherAPI.Authenticate to accept pairingId/terminalName or us…
Feb 9, 2015
7a7405b
Update language library version to 2.0.0
Feb 10, 2015
9005483
Add ToopherAPI.AdvancedApiUsageFactory
Feb 10, 2015
55d4e53
Try to create new Guid without assigning to var
Feb 10, 2015
023e8d6
Clean up and add tests
Feb 10, 2015
39616bb
Clean up ToopherAPI.Authenticate
Feb 10, 2015
522d363
Rename ToopherAPI to ToopherApi
Feb 11, 2015
7462aa4
Add ToopherApi.AdvancedApiUsageFactory.Pairings
Feb 11, 2015
c055a94
Add ToopherApi.AdvancedApiUsageFactory.Pairings.GetById
Feb 11, 2015
6299f3c
Remove old GetPairing and GetAuthenticationRequest
Feb 11, 2015
6ba790e
Move get(), post(), request() to ToopherApi.AdvancedApiUsageFactory.A…
Feb 11, 2015
d7d884e
Add ToopherApi.AdvancedApiUsageFactory.AuthenticationRequests
Feb 11, 2015
6a80a56
Add User object and ToopherApi.AdvancedApiUsageFactory.Users.GetById
Feb 11, 2015
85ecffb
Add ToopherApi.AdvancedApiUsageFactory.Users.Create
Feb 11, 2015
41fa5ee
Add UserTerminal object and ToopherApi.AdvancedApiUsageFactory.UserTe…
Feb 11, 2015
ac28a90
Add ToopherApi.AdvancedApiUsageFactory.UserTerminals.Create
Feb 11, 2015
a94ffe1
Add ToopherApi.AdvancedApiUsageFactory.Users.GetByName
Feb 11, 2015
08d580a
Update Pairing field names
Feb 11, 2015
f6f0ce9
Add Pairing.api
Feb 11, 2015
c34d7ca
Add Pairing.RefreshFromServer and Update
Feb 11, 2015
fe57805
Add UserTerminal.api and update field names
Feb 11, 2015
1f7b17b
Add User.api and update field names
Feb 11, 2015
c2be0f1
Add User.RefreshFromServer and Update
Feb 11, 2015
6f636fa
Add UserTerminal.RefreshFromServer and Update
Feb 11, 2015
b4e2504
Add Action object
Feb 11, 2015
207270b
Add AuthenticationRequest.api and update field names
Feb 12, 2015
cddc81b
Add Action.Update
Feb 12, 2015
06eef93
Add AuthenticationRequest.RefreshFromServer and Update
Feb 12, 2015
5945461
Add AuthenticationRequest.GrantWithOtp
Feb 12, 2015
0530085
Add User.EnableToopherAuthentication and DisableToopherAuthentication
Feb 12, 2015
a7488b1
Add User.Reset
Feb 12, 2015
3c34859
Add Pairing.GetResetLink
Feb 12, 2015
a057f14
Add Pairing.EmailResetLink
Feb 12, 2015
0f90aa4
Add Pairing.GetQrCodeImage
Feb 12, 2015
ac6d79f
Add test for ToopherApi.AdvancedApiUsageFactory.Users.GetByName
Feb 12, 2015
7287867
Cleanup PairingEmailResetLinkTest
Feb 12, 2015
7d6be3b
Add ToopherIframe class
Feb 16, 2015
bdc28cd
Add ToopherIframe.ValidatePostback and Signature
Feb 16, 2015
cad4e21
Change OAuthTools.Concatenate public to use in ToopherIframe.UrlEncod…
Feb 17, 2015
3856d79
Add OAuthTools.nonceOverride for testing
Feb 17, 2015
87c207f
Add OAuth.dateOverride for testing
Feb 17, 2015
f48e8ba
Add ToopherIframe.GetAuthenticationUrl and GetUserManagementUrl
Feb 17, 2015
5e64ffa
Remove old duplicate methods and tests
Feb 17, 2015
2eb80fc
Split tests into TestFixtures for each class
Feb 17, 2015
3dfa195
Add constants for testing
Feb 17, 2015
3292dcf
Rename getApi to getToopherApi
Feb 17, 2015
0826017
Add tests for ToopherIframe version and baseUrl
Feb 17, 2015
4ce9e4c
Add test for create User, UserTerminal, Action, Pairing and Authentic…
Feb 17, 2015
38ce5f7
Update ToopherIframe constants to allow for testing
Feb 17, 2015
c6994a3
Reorder ToopherIframe methods
Feb 17, 2015
088e4ef
Remove webClientProxyType from ToopherIframe and fix DEFAULT_BASE_URL
Feb 18, 2015
21f0e38
Add XML doc comments for ToopherIframe
Feb 18, 2015
549e419
Add XML doc comments for ToopherApi
Feb 18, 2015
0d9803e
Add XML doc comments for Pairing
Feb 18, 2015
0e4f03c
Add XML doc comments for AuthenticationRequest
Feb 18, 2015
d2a3d5d
Add XML doc comments for User
Feb 18, 2015
f059429
Add XML doc comments for UserTerminal
Feb 18, 2015
221d6b8
Add XML doc comments for Action
Feb 18, 2015
78d88db
Throw SignatureValidationError if there's an error while calculating …
Feb 18, 2015
2c8f1e5
Rename terminal_name_extra to requester_specified_terminal_id
Feb 18, 2015
f67e25c
Fix spacing
Feb 18, 2015
fa30cce
Update ToopherDotNetDemo
Feb 18, 2015
f24c95d
Update ToopherZeroStorageDemo
Feb 18, 2015
e87832c
Update README with new api.Pair() and api.Authenticate()
Feb 19, 2015
1cbc151
Make corrections in README
Feb 19, 2015
3a2ac0e
Return new User from Users.getByName instead of getById
Feb 19, 2015
776b27a
Used named parameters for ToopherApi.Authenticate
Feb 19, 2015
7c5875a
Add ToopherObjectFactory for Users, UserTerminals, AuthenticationRequ…
Feb 20, 2015
df4eeaf
Cleanup ToopherIframe.Signature
Feb 23, 2015
698c93a
Cleanup demo
Feb 25, 2015
b26a278
Update README
Feb 25, 2015
219a8af
Fix typo in test assertion message
Feb 25, 2015
564e486
Add instructions for running demo
Feb 25, 2015
6e98c58
Fix spacing and braces to follow C# conventions
Feb 25, 2015
0da3bd0
Remove unnecessary line from demo
Feb 25, 2015
5a58c3b
Remove unnecessary comment
Feb 25, 2015
37ba1c5
Refactor DateOverride to not use nullable type
Feb 25, 2015
386ccfd
Cleanup spacing
Feb 25, 2015
0a15895
Reorder args for Pair test and add assertions
Feb 25, 2015
3cd4fee
Add overload for validatePostback
Feb 26, 2015
2ea6517
Set default resetEmail, requestToken and requesterMetadata to empty s…
Mar 11, 2015
612d67c
Add Iframe version and expires to params in GetOauthUrl
Mar 11, 2015
b14895a
Use Int32.Parse for ttl
Mar 11, 2015
b0d2493
Refactor ValidatePostback into smaller methods
Mar 12, 2015
251c494
Capitalize method names
Mar 12, 2015
97f829b
Cast to IDictionary instead of JsonObject in AuthenticationRequest, P…
Mar 12, 2015
7578519
Replace ValidatePostback with ProcessPostback
Mar 12, 2015
1077dad
Add ToopherIframe.IsAuthenticationGranted
Mar 18, 2015
f959ea7
Add test for IsAuthenticationGranted when auth request is granted and…
Mar 20, 2015
0279659
Fix typo in docs
Mar 23, 2015
2765a0b
Cleanup text in demo
Mar 23, 2015
dfc0fde
Add js for ToopherIframe
Mar 23, 2015
4857289
Include baseUrl when creating new instance of ToopherApi
Mar 24, 2015
6f066b6
Add MIT license
Mar 25, 2015
70efc71
Trim extra comma from authorization header in OAuth lib
Mar 25, 2015
44fa5b8
Add more tests to increase coverage
Mar 25, 2015
e38e8e8
Cleanup ToopherIframe and ToopherApi
Mar 25, 2015
4aca72c
Add license to README
Mar 26, 2015
4247336
Add ProcessPostback test for keys with empty values
Mar 30, 2015
2278ac4
Simplify README and add iframe info
Mar 31, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions CONTRIBUTING.md

This file was deleted.

7 changes: 7 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Copyright (c) 2012 Toopher, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
106 changes: 79 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,104 @@
#ToopherDotNet
#ToopherDotNet [![Build Status](https://travis-ci.org/toopher/toopher-dotnet.png?branch=master)](https://travis-ci.org/toopher/toopher-dotnet)

[![Build
Status](https://travis-ci.org/toopher/toopher-dotnet.png?branch=master)](https://travis-ci.org/toopher/toopher-dotnet)

#### Introduction
ToopherDotNet is a Toopher API library that simplifies the task of interfacing with the Toopher API from DotNet programs. It does not depend on any external libraries, and preconfigures the required OAuth and JSON functionality so you can focus on just using the API.

#### Learn the Toopher API
Make sure you visit (http://dev.toopher.com) to get acquainted with the Toopher API fundamentals. The documentation there will tell you the details about the operations this API wrapper library provides.

#### OAuth Authentication

The first step to accessing the Toopher API is to sign up for an account at the development portal (http://dev.toopher.com) and create a "requester". When that process is complete, your requester is issued OAuth 1.0a credentials in the form of a consumer key and secret. Your key is used to identify your quester when Toopher interacts with your customers, and the secret is used to sign each request so that we know it is generated by you. This library properly formats each request with your credentials automatically.
### .NET Framework Version
\>=4.5

#### The Toopher Two-Step
Interacting with the Toopher web service involves two steps: pairing, and authenticating.
### C# Version
\>=5.0

##### Pair
Before you can enhance your website's actions with Toopher, your customers will need to pair their phone's Toopher app with your website. To do this, they generate a unique, nonsensical "pairing phrase" from within the app on their phone. You will need to prompt them for a pairing phrase as part of the Toopher enrollment process. Once you have a pairing phrase, just send it to the Toopher API along with your requester credentials and we'll return a pairing ID that you can use whenever you want to authenticate an action for that user.
### Documentation
Make sure you visit [https://dev.toopher.com](https://dev.toopher.com) to get acquainted with the Toopher API fundamentals. The documentation there will tell you the details about the operations this API wrapper library provides.

##### Authenticate
You have complete control over what actions you want to authenticate using Toopher (for example: logging in, changing account information, making a purchase, etc.). Just send us the user's pairing ID, a name for the terminal they're using, and a description of the action they're trying to perform and we'll make sure they actually want it to happen.
## ToopherApi Workflow

#### Librarified
This library makes it super simple to do the Toopher two-step. Check it out:
### Step 1: Pair
Before you can enhance your website's actions with Toopher, your customers will need to pair their mobile device's Toopher app with your website. To do this, they generate a unique pairing phrase from within the app on their mobile device. You will need to prompt them for a pairing phrase as part of the Toopher enrollment process. Once you have a pairing phrase, just send it to the Toopher API along with your requester credentials and we'll return a pairing ID that you can use whenever you want to authenticate an action for that user.

```csharp
using Toopher;

// Create an API object using your credentials
ToopherApi api = new ToopherApi("<your consumer key>", "<your consumer secret>");

// Step 1 - Pair with their phone's Toopher app
PairingStatus pairing = api.Pair("pairing phrase", "username@yourservice.com");
// Step 1 - Pair with their mobile device's Toopher app
Pairing pairing = api.Pair("username@yourservice.com", "pairing phrase");
```

### Step 2: Authenticate
You have complete control over what actions you want to authenticate using Toopher (logging in, changing account information, making a purchase, etc.). Just send us the username or pairing ID and we'll make sure they actually want it to happen. You can also choose to provide the following optional parameters: terminal name, requester specified ID and action name (*default: "Log in"*).


```csharp
// Step 2 - Authenticate a log in
AuthenticationStatus auth = api.Authenticate(pairing.id, "my computer");
AuthenticationRequest authenticationRequest = api.Authenticate("username@yourservice.com", "terminal name");

// Once they've responded you can then check the status
AuthenticationStatus status = api.GetAuthenticationStatus(auth.id);
if (auth.pending == false && auth.granted == true) {
authenticationRequest.RefreshFromServer();
if (authenticationRequest.pending == false && authenticationRequest.granted == true) {
// Success!
}
```

#### Handling Errors
## ToopherIframe Workflow

### Step 1: Embed a request in an IFRAME
1. Generate an authentication URL by providing a username.
2. Display a webpage to your user that embeds this URL within an `<iframe>` element.

```csharp
using Toopher;

// Create an API object using your credentials
ToopherIframe iframeApi = new ToopherIframe("<your consumer key>", "<your consumer secret>");

string authenticationIframeUrl = iframeApi.GetAuthenticationUrl("username@yourservice.com");

// Add an <iframe> element to your HTML:
// <iframe id="toopher-iframe" src=authenticationIframeUrl />
```

### Step 2: Validate the postback data

The simplest way to validate the postback data is to call `IsAuthenticationGranted` to check if the authentication request was granted.

```csharp
// Retrieve the postback data as a string from POST parameter 'iframe_postback_data'

// Returns boolean indicating if authentication request was granted by user
bool authenticationRequestGranted = iframeApi.IsAuthenticationGranted(postbackData);

if (authenticationRequestGranted) {
// Success!
}
```

### Handling Errors
If any request runs into an error a `RequestError` will be thrown with more details on what went wrong.

#### Try it out
Check out the `ToopherDotNetDemo` project for an example program that walks you through the whole process!
### Demo
Check out the `ToopherDotNetDemo` for an example program that walks you through the whole process! Simply run the commands below:
```shell
$ xbuild
$ mono ToopherDotNetDemo/bin/Debug/ToopherDotNetDemo.exe
```

## Contributing
### Dependencies
This library was developed on Windows and OS X. To run .NET on OS X, we use [Mono](http://www.mono-project.com/). To install Mono with Homebrew run:
```shell
$ brew install mono
```

### Tests
To run the tests enter:

```shell
$ xbuild
$ nunit-console ./ToopherDotNetTests/bin/Debug/ToopherDotNetTests.dll -exclude Integration,NotWorkingOnMono
```


## License
ToopherDotNet is licensed under the MIT License. See LICENSE.txt for the full text.
2 changes: 1 addition & 1 deletion ToopherDotNet/OAuth/OAuthRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ private string WriteAuthorizationHeader(WebParameterCollection parameters)
}

var authorization = sb.ToString();
return authorization;
return authorization.TrimEnd(new char[]{ ',' });
}

#endregion
Expand Down
24 changes: 23 additions & 1 deletion ToopherDotNet/OAuth/OAuthTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ public static class OAuthTools

private static readonly Random _random;
private static readonly object _randomLock = new object();
private static string nonceOverride;

public static void SetNonceOverride (string nonceOverride)
{
OAuthTools.nonceOverride = nonceOverride;
}

private static DateTime dateOverride;

public static void SetDateOverride (DateTime dateOverride)
{
OAuthTools.dateOverride = dateOverride;
}


#if !SILVERLIGHT
private static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create();
Expand Down Expand Up @@ -49,6 +63,9 @@ static OAuthTools()
/// <returns></returns>
public static string GetNonce()
{
if (nonceOverride != null){
return nonceOverride;
} else {
const string chars = (Lower + Digit);

var nonce = new char[16];
Expand All @@ -60,6 +77,7 @@ public static string GetNonce()
}
}
return new string(nonce);
}
}

/// <summary>
Expand All @@ -69,7 +87,11 @@ public static string GetNonce()
/// <returns></returns>
public static string GetTimestamp()
{
if (dateOverride == default(DateTime)) {
return GetTimestamp(DateTime.UtcNow);
} else {
return GetTimestamp(dateOverride);
}
}

/// <summary>
Expand Down Expand Up @@ -164,7 +186,7 @@ public static string NormalizeRequestParameters(WebParameterCollection parameter
return concatenated;
}

private static string Concatenate(ICollection<WebParameter> collection, string separator, string spacer)
public static string Concatenate(ICollection<WebParameter> collection, string separator, string spacer)
{
var sb = new StringBuilder();

Expand Down
Loading