diff --git a/OwinOAuthProviders.sln b/OwinOAuthProviders.sln
index f22edb8..3e28843 100644
--- a/OwinOAuthProviders.sln
+++ b/OwinOAuthProviders.sln
@@ -112,6 +112,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Pod
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.ArcGISPortal", "src\Owin.Security.Providers.ArcGISPortal\Owin.Security.Providers.ArcGISPortal.csproj", "{18547CA4-D7D3-43C2-81C2-A21FC8151A93}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Typeform", "src\Owin.Security.Providers.Typeform\Owin.Security.Providers.Typeform.csproj", "{C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -338,6 +340,10 @@ Global
{18547CA4-D7D3-43C2-81C2-A21FC8151A93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18547CA4-D7D3-43C2-81C2-A21FC8151A93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18547CA4-D7D3-43C2-81C2-A21FC8151A93}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/OwinOAuthProvidersDemo/App_Start/Startup.Auth.cs b/OwinOAuthProvidersDemo/App_Start/Startup.Auth.cs
index 3cf891a..dfae802 100755
--- a/OwinOAuthProvidersDemo/App_Start/Startup.Auth.cs
+++ b/OwinOAuthProvidersDemo/App_Start/Startup.Auth.cs
@@ -5,6 +5,7 @@ using Owin;
using Owin.Security.Providers.Evernote;
using Owin.Security.Providers.PayPal;
using Owin.Security.Providers.ArcGISPortal;
+using Owin.Security.Providers.Typeform;
namespace OwinOAuthProvidersDemo
{
@@ -357,6 +358,17 @@ namespace OwinOAuthProvidersDemo
// AppSecret = "",
// DebugUsingRequestHeadersToBuildBaseUri = true
//});
+
+ // WARNING:
+ // Typeform doesn't supply the user's ID so use this provider for authorization only, not authentication
+ // because each time you sign in with the same Typeform account it will yield a distinct UserId.
+ //var typeformOptions = new Owin.Security.Providers.Typeform.TypeformAuthenticationOptions
+ //{
+ // ClientId = "",
+ // ClientSecret = "",
+ //};
+ //typeformOptions.Scope.Add("forms:read");
+ //app.UseTypeformAuthentication(typeformOptions);
}
- }
+ }
}
\ No newline at end of file
diff --git a/OwinOAuthProvidersDemo/OwinOAuthProvidersDemo.csproj b/OwinOAuthProvidersDemo/OwinOAuthProvidersDemo.csproj
index dcb8075..67c3177 100644
--- a/OwinOAuthProvidersDemo/OwinOAuthProvidersDemo.csproj
+++ b/OwinOAuthProvidersDemo/OwinOAuthProvidersDemo.csproj
@@ -431,6 +431,10 @@
{c3cf8734-6aac-4f59-9a3e-1cba8582cd48}
Owin.Security.Providers.Twitch
+
+ {c8862b45-e1d1-4ab7-a83d-3a2fd2a22526}
+ Owin.Security.Providers.Typeform
+
{3e89eca3-f4e7-4181-b26b-8250d5151044}
Owin.Security.Providers.Untappd
diff --git a/src/Owin.Security.Providers.Typeform/Constants.cs b/src/Owin.Security.Providers.Typeform/Constants.cs
new file mode 100644
index 0000000..6acbe32
--- /dev/null
+++ b/src/Owin.Security.Providers.Typeform/Constants.cs
@@ -0,0 +1,7 @@
+namespace Owin.Security.Providers.Typeform
+{
+ public static class Constants
+ {
+ public const string DefaultAuthenticationType = "Typeform";
+ }
+}
\ No newline at end of file
diff --git a/src/Owin.Security.Providers.Typeform/Owin.Security.Providers.Typeform.csproj b/src/Owin.Security.Providers.Typeform/Owin.Security.Providers.Typeform.csproj
new file mode 100644
index 0000000..83e9c4a
--- /dev/null
+++ b/src/Owin.Security.Providers.Typeform/Owin.Security.Providers.Typeform.csproj
@@ -0,0 +1,107 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}
+ Library
+ Properties
+ Owin.Security.Providers.Typeform
+ Owin.Security.Providers.Typeform
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ 6
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ 6
+
+
+
+ ..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
+ True
+
+
+ ..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll
+ True
+
+
+ ..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+ ..\..\packages\Owin.1.0\lib\net40\Owin.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Resources.resx
+ True
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PostBuildEventDependsOn);
+ PostBuildMacros;
+
+
+
\ No newline at end of file
diff --git a/src/Owin.Security.Providers.Typeform/Properties/AssemblyInfo.cs b/src/Owin.Security.Providers.Typeform/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8679e19
--- /dev/null
+++ b/src/Owin.Security.Providers.Typeform/Properties/AssemblyInfo.cs
@@ -0,0 +1,15 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Owin.Security.Providers.Typeform")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Owin.Security.Providers.Typeform")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("b6a4a4cb-d365-41a0-b4c9-966e7ef19de0")]
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
diff --git a/src/Owin.Security.Providers.Typeform/Provider/ITypeformAuthenticationProvider.cs b/src/Owin.Security.Providers.Typeform/Provider/ITypeformAuthenticationProvider.cs
new file mode 100644
index 0000000..6e71239
--- /dev/null
+++ b/src/Owin.Security.Providers.Typeform/Provider/ITypeformAuthenticationProvider.cs
@@ -0,0 +1,24 @@
+using System.Threading.Tasks;
+
+namespace Owin.Security.Providers.Typeform
+{
+ ///
+ /// Specifies callback methods which the invokes to enable developer control over the authentication process. />
+ ///
+ public interface ITypeformAuthenticationProvider
+ {
+ ///
+ /// Invoked whenever Typeform successfully authenticates a user
+ ///
+ /// Contains information about the login session as well as the user .
+ /// A representing the completed operation.
+ Task Authenticated(TypeformAuthenticatedContext context);
+
+ ///
+ /// Invoked prior to the being saved in a local cookie and the browser being redirected to the originally requested URL.
+ ///
+ ///
+ /// A representing the completed operation.
+ Task ReturnEndpoint(TypeformReturnEndpointContext context);
+ }
+}
\ No newline at end of file
diff --git a/src/Owin.Security.Providers.Typeform/Provider/TypeformAuthenticatedContext.cs b/src/Owin.Security.Providers.Typeform/Provider/TypeformAuthenticatedContext.cs
new file mode 100644
index 0000000..b6a30e4
--- /dev/null
+++ b/src/Owin.Security.Providers.Typeform/Provider/TypeformAuthenticatedContext.cs
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Security.Claims;
+using Microsoft.Owin;
+using Microsoft.Owin.Security;
+using Microsoft.Owin.Security.Provider;
+
+namespace Owin.Security.Providers.Typeform
+{
+ ///
+ /// Contains information about the login session as well as the user .
+ ///
+ public class TypeformAuthenticatedContext : BaseContext
+ {
+ ///
+ /// Initializes a
+ ///
+ /// The OWIN environment
+ /// The JSON-serialized user
+ /// Typeform Access token
+ /// Typeform Refresh token
+ /// Typeform instance url
+ public TypeformAuthenticatedContext(IOwinContext context, string accessToken)
+ : base(context)
+ {
+ AccessToken = accessToken;
+
+ // Typeform doesn't supply a unique identifier for the user,
+ // so we generate a fake one because OWIN pipeline requires it
+ // This means you can only use Typeform OAuth for authorization, not authentication because
+ // each time you sign in with the same Typeform account this provider will yield a distinct UserId
+ UserId = Guid.NewGuid().ToString();
+ }
+
+ ///
+ /// Gets the Typeform access token
+ ///
+ public string AccessToken { get; private set; }
+
+ ///
+ /// Gets the Typeform User ID
+ ///
+ [Obsolete("This is not the real UserId because Typeform OAuth endpoint does not provide it. Use Typeform OAuth for authorization, not authentication.")]
+ public string UserId { get; private set; }
+
+
+ ///
+ /// Gets the representing the user
+ ///
+ public ClaimsIdentity Identity { get; set; }
+
+ ///
+ /// Gets or sets a property bag for common authentication properties
+ ///
+ public AuthenticationProperties Properties { get; set; }
+ }
+}
diff --git a/src/Owin.Security.Providers.Typeform/Provider/TypeformAuthenticationProvider.cs b/src/Owin.Security.Providers.Typeform/Provider/TypeformAuthenticationProvider.cs
new file mode 100644
index 0000000..1c34734
--- /dev/null
+++ b/src/Owin.Security.Providers.Typeform/Provider/TypeformAuthenticationProvider.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Owin.Security.Providers.Typeform
+{
+ ///
+ /// Default implementation.
+ ///
+ public class TypeformAuthenticationProvider : ITypeformAuthenticationProvider
+ {
+ ///
+ /// Initializes a
+ ///
+ public TypeformAuthenticationProvider()
+ {
+ OnAuthenticated = context => Task.FromResult