Compare commits

...

184 Commits

Author SHA1 Message Date
Tommy Parnell
3e0b467249 working rc 2016-04-22 23:50:05 -04:00
Tommy Parnell
1ea4fdaf93 add some rake for managing nuspecs 2016-04-22 22:44:47 -04:00
Eonasdan
e1fc9e108b massive change to the solution (#151)
Nice work...I'm not in love with the fact that it still has that github change in it, but I'll take it...I don't think its too dangerous.

That being said breaking these packages apart is both very helpful, and not simple so thank you for that!

I'll plan on publishing to nuget later this week after some testing...
2016-04-18 08:49:34 -04:00
Jerrie Pelser
14905887ec Merge pull request #142 from 2020IP/master
Added GivenName and FamilyName claim types that LinkedIn returns.
2016-02-25 15:24:58 -06:00
Jerrie Pelser
1bad22de21 Merge pull request #144 from D4rkTiger/master
Add new provider DoYouBuzz
2016-02-18 09:40:16 -06:00
Eric Green
3b027098d7 Set username back to having a value 2016-02-15 12:08:29 -06:00
Eric Green
57dcb5863c Marked username as obsolete. 2016-02-15 10:31:02 -06:00
Eric Green
939ec99564 Added urn:linkedin:name claim back. 2016-02-15 08:09:03 -06:00
Yoann Blossier
1a5b85eebe Add new provider DoYouBuzz
Add new french provider DoYouBuzz, a website which hosts CVs
2016-02-11 09:53:17 +01:00
Jerrrie Pelser
a90b71727b Release V1.27 2016-02-10 11:12:45 -06:00
Jerrie Pelser
0abe888128 Merge pull request #140 from D4rkTiger/master
Add new provider : Xing
2016-02-10 10:55:08 -06:00
Yoann Blossier
fb0f78c250 Clean project
Remove C# 6 code (VKontakte and Xing)
Remove package allows us to build C#6 code under VS2013
Remove empty provider folder "DoYouBuzz"
2016-02-10 09:26:41 +01:00
Eric Green
aa2040a0a7 Added GivenName and FamilyName claim types that LinkedIn returns. Also moved formattedName to the Name claim type and removed the UserName proeprty because LinkedIn doesn't return a username 2016-01-28 08:39:11 -06:00
Yoann Blossier
53ea24bb48 Revert "Add DoYouBuzz provider"
This reverts commit 95e2e4f207.
2016-01-07 10:35:38 +01:00
Yoann Blossier
95e2e4f207 Add DoYouBuzz provider
Add DoYouBuzz provider to authenticate with french CV provider account
2016-01-07 10:34:16 +01:00
Yoann Blossier
92e67e5eef Add new provider : Xing
Add Xing provider to authenticate with german professional social
network account
2016-01-06 16:19:36 +01:00
Jerrie Pelser
344336b536 Publish version 1.26 2016-01-02 14:37:58 +02:00
Jerrie Pelser
e8f7c50094 Merge pull request #138 from Uriil/master
Added VKontakte provider
2016-01-02 14:01:28 +02:00
Jerrie Pelser
b3f96ae700 Merge pull request #137 from paullooijmans/master
Implemented customizable profile fields for LinkedIn
2016-01-02 14:01:09 +02:00
Jerrie Pelser
ff3cc7edb1 Merge pull request #134 from jrummell/master
Added Bitbucket provider
2016-01-02 14:00:56 +02:00
Jerrie Pelser
f6e9bdf829 Merge pull request #131 from tatx/master
changing the user info endpoint
2016-01-02 13:59:11 +02:00
Jerrie Pelser
0f2329b102 Merge pull request #129 from MCCLogin/apsArcGIS
Fixed bug. Internal redirect was hard coded, changed to match quality…
2016-01-02 13:58:42 +02:00
Nikita Gusev
d0cf3a0543 Deleted unneded settings 2015-12-30 17:55:58 +01:00
Nikita Gusev
5167e83e94 Added VKontakte support 2015-12-30 17:51:37 +01:00
paullooijmans
fac48def4c Ensure the fields sent to LinkedIn are unique. If they're not LinkedIn throws an exception. 2015-12-09 13:48:25 +01:00
paullooijmans
fdf3a37dfd Implemented customizable profile fields for LinkedIn as specified in issue #43 2015-12-08 16:55:56 +01:00
jrummell
87f3eadd4f Finished Bitbucket implementation
Since Bitbucket does not support the CSRF state parameter, a few values
are stored as cookies.
2015-11-15 11:55:30 -05:00
jrummell
9a00f77ad0 Replaced GitHub OAuth flow with Bitbucket's in BitbucketAuthenticationHandler 2015-11-11 23:30:58 -05:00
jrummell
b27a4cbeaf Updated Bitbucket endpoints and comments 2015-11-10 21:37:56 -05:00
jrummell
feec4db5a9 Created Bitbucket folder copy/pasted from GitHub
Copy/pasted GibHub components to Bitbucket and renamed types.
2015-11-10 20:49:36 -05:00
Tathagata Chakraborty
9633cd844b changing the user info endpoint to one that does not require user permission for access to user personal information 2015-10-23 10:58:40 +05:30
RajkumarMondal
e4b60ca7dd Fixed bug. Internal redirect was hard coded, changed to match quality of other providers and remove hard coded paths.
Is now able to operate with controllers not named "Account" with any view/path instead of the previous hard coded path.
2015-10-12 23:51:32 +05:30
Jerrie Pelser
da994fcba2 Release version 1.25 2015-09-26 19:20:36 +07:00
Jerrie Pelser
4917cf0dfd Merge pull request #127 from tatx/master
Adding support for Onshape
2015-09-26 19:09:46 +07:00
Tathagata Chakraborty
f762770e00 updating the sample commented code in the Startup.Auth.cs file 2015-09-15 13:16:58 +05:30
Tathagata Chakraborty
063d2d515f fixing the comment on the CallbackPath property to reflect the correct default value 2015-09-15 13:11:17 +05:30
Tathagata Chakraborty
f4d5f0b23f removing the extra overloads from the middleware and setting a default value for the CallbackPath property 2015-09-15 13:09:54 +05:30
Tathagata Chakraborty
fba2ed5bae updating the Onshape spelling in the readme 2015-09-15 12:07:16 +05:30
Tathagata Chakraborty
f24669670d passing the state as a query parameter in /oauth/authorize 2015-09-15 12:03:09 +05:30
Tathagata Chakraborty
e73197a619 adding a configurable hostname when creating the onshape owin middleware 2015-09-15 11:09:57 +05:30
Tathagata Chakraborty
4f56f6387a adding an option to set the callback path 2015-09-15 10:52:18 +05:30
Tathagata Chakraborty
f0f580356f renaming the file prefixes from OnShape to Onshape 2015-09-15 09:55:38 +05:30
Tathagata Chakraborty
f8217d9175 renaming the prefix from incorrect OnShape to the correct Onshape with only the O capitalized 2015-09-15 09:35:41 +05:30
Tathagata Chakraborty
6600badf92 updating the readme 2015-09-14 15:49:33 +05:30
Tathagata Chakraborty
eac3ba64f9 removing some commented code 2015-09-14 15:46:08 +05:30
Tathagata Chakraborty
c9f9d3f92f adding the onshape provider 2015-09-14 15:43:24 +05:30
Jerrie Pelser
e35b98c8a4 Release version 1.24.1 2015-09-11 11:30:04 +07:00
Jerrie Pelser
76cb568775 Merge pull request #125 from teference/master
Added Shopify Domain Property to fetch after authorization
2015-09-11 10:53:32 +07:00
Jaspalsinh Chauhan
04ba5feaf9 Added Shopify Domain Property to fetch after authorization 2015-09-08 07:04:16 +05:30
Jerrie Pelser
6aaa96e388 Release version 1.24 2015-08-28 11:26:56 +07:00
Jerrie Pelser
5fea77d13e resolve conflicts 2015-08-28 11:12:55 +07:00
Jerrie Pelser
a478f182fe Merge branch 'benfoster-vimeo' 2015-08-28 11:10:21 +07:00
Jerrie Pelser
ba3a944284 Merge pull request #123 from jmloeffler/master
Basic Fitbit OAuth Provider Implementation
2015-08-28 11:07:38 +07:00
Ben Foster
6125132736 Added Vimeo OAuth 2 Provider. 2015-08-27 16:53:36 +01:00
Jason Loeffler
f94a869e7d Merge remote-tracking branch 'upstream/master'
Conflicts:
	OwinOAuthProvidersDemo/App_Start/Startup.Auth.cs
2015-08-24 12:28:53 -05:00
Jason Loeffler
57275803eb Added Fitbit to the repo markdown file. 2015-08-23 14:44:55 -05:00
Jason Loeffler
4ddc66c002 Initial Fitbit provider implementation. 2015-08-23 13:52:28 -05:00
Jerrie Pelser
ace291da70 Release version 1.23 2015-08-19 11:16:21 +07:00
Jerrie Pelser
7205001ff3 Remove C# 6 features 2015-08-19 11:13:18 +07:00
Jerrie Pelser
2a9d515ae5 Merge pull request #122 from kvoyk/master
Cosign provider for Identity Server
2015-08-19 10:58:22 +07:00
Jerrie Pelser
57a0ce35bf Merge pull request #121 from teference/master
Shopify OAuth provider - OWIN integration / implementation
2015-08-19 10:55:14 +07:00
Jaspalsinh Chauhan
bb2800cd03 Removed nameof for ArgumentNullException that is specific to C# 6.0 2015-08-17 10:26:07 +05:30
Jerrie Pelser
96b151bf9d Merge pull request #119 from takashi-uesaka/backlog
Backlog Security BugFix
2015-08-17 11:24:59 +07:00
Jaspalsinh Chauhan
0600b9b06c Shopify OAuth provider - OWIN integration / implementation 2015-08-13 00:25:57 +05:30
takashi uesaka
239a603798 Security BugFix.
I use HttpRequestMessage.Headers.Authorization instead of httpClient.DefaultRequestHeaders
2015-08-11 11:22:48 +09:00
Jerrie Pelser
9ccb01fd84 Merge pull request #117 from takashi-uesaka/backlog
BugFix.
2015-07-31 14:00:48 +07:00
takashi uesaka
5bca51d919 BugFix.
Clear authorization header before request access token.
Backlog OAuth Provider check the old token in authorization header and return 400 error.
2015-07-31 15:34:57 +09:00
kvoyk
9e16b8919c Update Startup.Auth.cs 2015-07-30 07:52:46 -04:00
Jerrie Pelser
7cae1b07d9 Release version 1.22.1 2015-07-30 17:44:50 +07:00
Jerrie Pelser
033fa701d1 Merge pull request #116 from spencerthang/master
Add support for the prompt parameter in Salesforce
2015-07-30 06:54:06 +07:00
kvoyk
e90385ad83 Update README.md 2015-07-29 19:05:44 -04:00
Spencer Thang
0c279e73f0 Add support for the prompt parameter in Salesforce 2015-07-29 14:34:03 +01:00
Kurt
f89a2cd13d Added Cosign provider 2015-07-28 09:31:45 -04:00
Jerrie Pelser
291a70f079 Release Version 1.22 2015-07-27 11:30:23 +07:00
Jerrie Pelser
9c8847c661 Merge pull request #115 from takashi-uesaka/backlog
Add Backlog Provider
2015-07-27 11:23:49 +07:00
takashi uesaka
8313e164cf Add default value for CallbackPath in BacklogAuthenticationOptions constructor 2015-07-24 16:30:05 +09:00
takashi uesaka
00ab4b4ccd Add Backlog to Readme.md 2015-07-23 19:42:43 +09:00
takashi uesaka
87c208f784 Add Backlog provider 2015-07-23 19:28:17 +09:00
Jerrie Pelser
12a129164d Merge pull request #114 from CrustyJew/master
Reddit UserAgent Option and token fix
2015-07-18 07:51:52 +07:00
CrustyJew
73400f62e0 Reddit UserAgent Option and token fix
-Add UserAgent property to RedditAuthenticationOptions
-Fix discarded "var request" in RedditAuthenticationHandler and add header to request
2015-07-17 09:18:35 -05:00
Jerrie Pelser
47b9e5b961 Merge branch 'kappa7194-imgur' 2015-07-17 10:06:01 +07:00
Albireo
70fae47aa7 Fill XML documentation (part 2) 2015-07-14 21:33:09 +02:00
Albireo
344b4a8074 Fill XML documentation (part 1) 2015-07-13 19:42:11 +02:00
Albireo
e75341d38c Reorder methods, fix method name 2015-07-13 19:41:17 +02:00
Albireo
912ad402d2 Refactor code 2015-07-13 19:05:08 +02:00
Albireo
46a06e6844 Add XML documentation markup 2015-07-13 18:50:24 +02:00
Albireo
3f8adc48a8 Add exceptions messages 2015-07-13 18:50:04 +02:00
Albireo
857afa28bc Reformat code 2015-07-13 18:38:30 +02:00
Albireo
fd02b65a12 Remove magic strings 2015-07-13 18:32:55 +02:00
Albireo
f3c6458ec8 Clean up code 2015-07-09 00:01:07 +02:00
Albireo
a368381877 Implement imgur authentication handler 2015-07-08 23:39:35 +02:00
Albireo
dd9c4be1c3 Implement imgur authenticated context 2015-07-08 23:39:16 +02:00
Albireo
f5f6cda67e Fix imgur authentication options caption 2015-07-08 23:38:57 +02:00
Albireo
702afe3288 Implement imgur authentication provider 2015-07-08 23:38:36 +02:00
Albireo
65aefd97ec Implement imgur middleware 2015-07-08 22:40:57 +02:00
Albireo
d3365fcb5c Add imgur authentication registration 2015-07-08 22:24:35 +02:00
Albireo
0944fd9fae Add imgur authentication options 2015-07-08 22:24:09 +02:00
Albireo
95d20648e4 Fix imgur middleware constructor 2015-07-08 22:17:06 +02:00
Albireo
2f9fb9f106 Add imgur provider classes stubs 2015-07-07 10:20:15 +02:00
Jerrie Pelser
e61b9db350 Release version 1.21 2015-06-25 20:01:20 +07:00
Jerrie Pelser
505d361f84 Merge pull request #106 from Lorac/master
Gitter Authentication
2015-06-25 19:48:48 +07:00
Maxime Roussin-Belanger
d5050c3a46 Fixed copy paste error + private setter 2015-06-25 08:34:38 -04:00
Maxime Roussin-Bélanger
0051727d92 Update OwinOAuthProviders.sln
Changed back the right version of Visual studio
2015-06-24 22:15:38 -04:00
Maxime Roussin-Bélanger
248a48dfed Update Startup.Auth.cs
Removed teamid in slack
2015-06-24 22:14:00 -04:00
Maxime Roussin-Bélanger
a74c560258 Merge pull request #2 from Lorac/feature/gitter-provider
Feature/gitter provider
2015-06-24 22:08:40 -04:00
Maxime Roussin-Belanger
aa0d0b934b Added gitter authentication 2015-06-24 22:07:21 -04:00
Maxime Roussin-Belanger
076edb794f Can log with gitter account 2015-06-24 22:05:55 -04:00
Maxime Roussin-Belanger
4724d8847c Working Button, login broken for now 2015-06-23 23:52:21 -04:00
Maxime Roussin-Belanger
2633db8e07 Fixed constructors 2015-06-23 21:48:45 -04:00
Maxime Roussin-Belanger
a52191874c Saved the solution file 2015-06-22 23:03:50 -04:00
Maxime Roussin-Belanger
29e12caea4 Added the Gitter in the OAuth provider list 2015-06-22 23:00:05 -04:00
Maxime Roussin-Belanger
c7b2c9f920 Started development on Gitter 2015-06-22 22:57:44 -04:00
Maxime Roussin-Belanger
ea413c00ae Added the updated for vs2015 2015-06-22 22:57:22 -04:00
Jerrie Pelser
b2521b38ac Merge pull request #105 from Lorac/master
Alphabetized providers + added the ones missing …
2015-06-19 11:12:08 +07:00
Maxime Roussin-Bélanger
89ad748d7b alphabetize providers + added the ones missing
Added my name in the contribution ( Wargaming )
2015-06-18 16:44:24 -04:00
Jerrie Pelser
3072cd1312 Release version 1.20.1 2015-06-09 10:52:56 +07:00
Jerrie Pelser
38a049e9ad Merge pull request #102 from mitja-p/patch-1
Email was not acquired from Yahoo provider due to exception
2015-06-09 09:46:02 +07:00
mitja-p
18fa4b353e Email was not acquired from Yahoo provider due to exception 2015-06-05 16:32:01 +02:00
Jerrie Pelser
53242e94c9 Release version 1.20 2015-06-02 11:31:24 +07:00
Jerrie Pelser
a9a9db36cf Merge pull request #99 from mjknowles/master
Add Slack provider
2015-06-02 11:22:29 +07:00
Jerrie Pelser
4944f396c7 Name claim was stored twice with 2 different values
As per
http://stackoverflow.com/questions/5814017/what-is-the-purpose-of-nameidentifier-claim
I decided the correct value to be stored is the username, and not the
user's display name
2015-06-02 11:18:13 +07:00
mjknowles
d0783c35c1 Add Slack provider 2015-05-29 22:55:31 -05:00
Jerrie Pelser
9f9b3e94aa Release version 1.19 2015-05-16 09:47:34 +07:00
Jerrie Pelser
55b0d7bb28 Merge pull request #98 from Res42/master
Add Spotify provider
2015-05-15 18:43:36 +07:00
Adam Reisinger
28ce309084 Add Spotify provider 2015-05-15 13:17:50 +02:00
Jerrie Pelser
64955b9a0b Release version 1.18 2015-05-04 14:21:01 +07:00
Jerrie Pelser
2f865e46fb Merge pull request #91 from tparnell8/deviant
add deviantArt provider #90
2015-05-04 13:57:19 +07:00
Tommy Parnell
050c69522f fix some weird build errors, probably related to merging 2015-05-02 12:35:12 -04:00
Tommy Parnell
b030a0ef62 fix merge 2015-05-02 12:32:32 -04:00
Tommy Parnell
44a0618f8f lowercase url 2015-05-02 12:31:33 -04:00
Tommy Parnell
399bee18b8 flatten commits, provide deviantArt support 2015-05-02 12:30:20 -04:00
Jerrie Pelser
04e2b1ff2a Merge pull request #75 from tparnell8/master
untappd support
2015-05-02 23:10:43 +07:00
Tommy Parnell
8fd73018a3 Merge branch 'master' of github.com:tparnell8/OwinOAuthProviders 2015-05-02 11:28:06 -04:00
Tommy Parnell
419d50301e use lowercase url 2015-05-02 11:27:53 -04:00
Tommy Parnell
38a6c5a300 include demo 2015-05-02 11:27:52 -04:00
rodkings
2c36d5bca2 Saving State by Cookie 2015-05-02 11:27:15 -04:00
Tommy Parnell
1fa83045ce stopping point 2015-05-02 11:27:14 -04:00
Tommy Parnell
e8e2f27a6e untappd support 2015-05-02 11:26:30 -04:00
Tommy Parnell
bc52966a7f lowercase url 2015-05-02 11:25:11 -04:00
Tommy Parnell
556858dbad Merge branch 'deviant' of github.com:tparnell8/OwinOAuthProviders into deviant 2015-05-02 11:24:14 -04:00
Tommy Parnell
c1bc79c9fd flatten commits, provide deviantArt support 2015-05-02 11:23:43 -04:00
Tommy Parnell
e0ed492864 use lowercase url 2015-05-02 11:18:21 -04:00
Jerrie Pelser
b941142fb2 Merge branch 'tparnell8-twitchReadme' 2015-05-02 21:26:56 +07:00
Jerrie Pelser
32e4f3bf52 resolve conflict 2015-05-02 21:26:31 +07:00
Jerrie Pelser
57b15aec08 Merge pull request #89 from JustMaier/master
Added Visual Studio Online oAuth support
2015-05-02 21:19:54 +07:00
Tommy Parnell
79a7882141 add twitch to list of OAuth 2015-04-20 12:06:45 -04:00
Tommy Parnell
40f4c94285 flatten commits, provide deviantArt support 2015-04-20 09:59:14 -04:00
Jerrie Pelser
766e7e542a Merge pull request #92 from tparnell8/addtparnell
add contributor
2015-04-20 17:31:40 +07:00
Tommy Parnell
ae89168511 shameless plug 2015-04-20 00:34:35 -04:00
Tommy Parnell
b072fda54a merge commit 2015-04-19 22:54:56 -04:00
Tommy Parnell
8b5e916a7c include demo 2015-04-19 22:39:27 -04:00
Tommy Parnell
a2ba96d6ad Merge pull request #1 from rodkings/master
Saving State by Cookie
2015-04-19 22:35:17 -04:00
rodkings
5318c1c788 Saving State by Cookie 2015-04-19 19:28:24 -06:00
Justin Maier
94eacc949f Add VSO Refresh Token 2015-04-16 20:12:49 -07:00
Justin Maier
3c738c4f5f Added Visual Studio Online oAuth support
https://www.visualstudio.com/integrate/get-started/auth/oauth
2015-04-16 18:36:11 -07:00
Jerrie Pelser
c03cb2b784 Oops, my bad. Added LI fix. release 1.17.1 2015-04-09 11:33:37 +07:00
Jerrie Pelser
1e6f75df06 Release version 1.17 2015-04-09 11:26:05 +07:00
Jerrie Pelser
307b6ce04a Merge branch 'master' of https://github.com/RockstarLabs/OwinOAuthProviders 2015-04-09 10:44:17 +07:00
Jerrie Pelser
ca81827264 Merge branch 'chebum-master' 2015-04-09 10:42:23 +07:00
Jerrie Pelser
faf4d1ac84 Add Flickr 2015-04-09 10:40:28 +07:00
Jerrie Pelser
cca8849cdf Merge pull request #78 from laedit/Simplify-steam-auth-overrides
Simplify Steam auth options overrides
2015-04-09 09:59:53 +07:00
Tommy Parnell
3e438209c9 stopping point 2015-04-08 22:59:06 -04:00
Jerrie Pelser
67c3691053 Merge branch 'Lorac-master' 2015-04-09 09:57:55 +07:00
Jerrie Pelser
cf3d1f8b81 Add support for regions 2015-04-09 09:57:12 +07:00
Jerrie Pelser
baf27d215f Merge branch 'master' of https://github.com/Lorac/OwinOAuthProviders into Lorac-master 2015-04-09 09:25:45 +07:00
Jerrie Pelser
4bf4d34e7e Merge branch 'qanuj-master' 2015-04-09 09:22:11 +07:00
Jerrie Pelser
084f4fc284 Merge branch 'master' of https://github.com/qanuj/OwinOAuthProviders into qanuj-master 2015-04-09 09:10:35 +07:00
Maxime Roussin-Bélanger
d0981d98e1 Fixed documentation 2015-04-08 12:26:56 -04:00
Anuj Pandey
6bf11d0159 Update PayPalAuthenticationOptions.cs 2015-04-08 17:43:20 +05:30
Jerrie Pelser
9fcff451f9 Merge branch 'master' of https://github.com/qanuj/OwinOAuthProviders into qanuj-master 2015-04-08 16:00:46 +07:00
Jerrie Pelser
d28f13defa Merge branch 'mariozski-battlenet-fix' 2015-04-08 15:29:56 +07:00
Jerrie Pelser
4bf2cbc1c0 Fix naming conventions while I'm at it... 2015-04-08 15:29:14 +07:00
Jerrie Pelser
75ffab45ae Merge branch 'battlenet-fix' of https://github.com/mariozski/OwinOAuthProviders into mariozski-battlenet-fix 2015-04-08 15:05:41 +07:00
Jerrie Pelser
b52f1feb07 Merge pull request #82 from Romoku/salesforce
Support Instance Url in Salesforce
2015-04-08 15:01:59 +07:00
qanuj
ce63ba6f4d UsePayPalAuthentication Added 2015-04-04 16:36:41 +05:30
mariozski
ae97f04d93 fixed Battle.net handler constructor 2015-03-29 16:49:39 +02:00
Maxime Roussin-Bélanger
fdd5ab6b1b Added comments 2015-03-28 16:02:11 -04:00
Maxime Roussin-Bélanger
4bda111678 Added modified csprof for wargaming 2015-03-28 16:00:19 -04:00
Maxime Roussin-Bélanger
56c641132f Added wargaming openid login 2015-03-28 15:59:49 -04:00
Romoku
57d8f8264d - Added InstanceUrl to SalesforceAuthenticatedContext
- Deserialize instance_url in SalesforceAuthenticationHandler

Update SalesforceAuthenticatedContext.cs

Update SalesforceAuthenticatedContext.cs
2015-03-26 00:56:28 -04:00
Ivan Nikitin
1eb34c4e83 Flickr - Fixes incorrect variable uses 2015-03-25 16:39:55 +01:00
Jérémie Bertrand
5a8dcfbd4b Simplify Steam auth options overrides 2015-03-25 07:15:46 +01:00
Ivan Nikitin
6d001e3e13 Flickr support 2015-03-24 19:14:26 +01:00
Tommy Parnell
50c07128cd untappd support 2015-03-22 17:13:28 -04:00
694 changed files with 34309 additions and 5848 deletions

71
.gitignore vendored
View File

@@ -1,34 +1,3 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
@@ -50,10 +19,16 @@ build/
[Bb]in/
[Oo]bj/
# Visual Studo 2015 cache/options directory
.vs/
Owin.Security.Providers.nuspec
Owin.Security.Providers*.nupkg
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
src/**/*.nuspec
src/**/*.nupkg
tools/
*_i.c
*_p.c
*.ilk
@@ -185,34 +160,4 @@ $RECYCLE.BIN/
# Mac crap
.DS_Store
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
/Output

6
Gemfile Normal file
View File

@@ -0,0 +1,6 @@
source 'http://rubygems.org'
gem 'rake'
gem 'os'
gem 'albacore'
gem 'nokogiri'

27
Gemfile.lock Normal file
View File

@@ -0,0 +1,27 @@
GEM
remote: http://rubygems.org/
specs:
albacore (2.0.4)
map (~> 6.5)
nokogiri (~> 1.5)
rake (> 10)
semver2 (~> 3.4)
map (6.6.0)
mini_portile2 (2.0.0)
nokogiri (1.6.7.2-x64-mingw32)
mini_portile2 (~> 2.0.0.rc2)
os (0.9.6)
rake (11.1.1)
semver2 (3.4.2)
PLATFORMS
x64-mingw32
DEPENDENCIES
albacore
nokogiri
os
rake
BUNDLED WITH
1.10.6

View File

@@ -1,34 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Owin.Security.Providers</id>
<version>1.16.0</version>
<authors>Jerrie Pelser and contributors</authors>
<owners>Jerrie Pelser</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>https://github.com/owin-middleware/OwinOAuthProviders</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Adds additional OAuth providers for OWIN to use with ASP.NET
</description>
<summary>
Additional OAuth providers for Katana (OWIN). Includes providers for LinkedIn, Yahoo, Google+, GitHub, Reddit, Instagram, StackExchange, SalesForce, TripIt, Buffer, ArcGIS, Dropbox, Wordpress, Battle.NET, Twitch and Yammer
Also adds generic OpenID 2.0 providers as well as a Steam-specific implementatio
</summary>
<releaseNotes>
Version 1.16
Added
- Added Foursquare Provider (Thank you Ricardo Peres - https://github.com/rjperes)
</releaseNotes>
<copyright>Copyright 2013, 2014</copyright>
<tags>owin katana oauth LinkedIn Yahoo Google+ GitHub Reddit Instagram StackExchange SalesForce TripIt Buffer ArcGIS Dropbox Wordpress Battle.NET Yammer OpenID Steam Twitch</tags>
<dependencies>
<dependency id="Microsoft.Owin.Security" version="2.1.0" />
<dependency id="Newtonsoft.Json" version="6.0.1" />
</dependencies>
</metadata>
<files>
<file src="..\Owin.Security.Providers\bin\Release\Owin.Security.Providers.dll" target="lib\net45" />
</files>
</package>

View File

@@ -1,218 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.ArcGISOnline
{
public class ArcGISOnlineAuthenticationHandler : AuthenticationHandler<ArcGISOnlineAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public ArcGISOnlineAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the ArcGISOnline user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?f=json&token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
var user = JsonConvert.DeserializeObject<Owin.Security.Providers.ArcGISOnline.Provider.ArcGISOnlineUser>(text);
var context = new ArcGISOnlineAuthenticatedContext(Context, user, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim("urn:ArcGISOnline:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:ArcGISOnline:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
context.Properties = new AuthenticationProperties
{
RedirectUri = baseUri +
"/Account/ExternalLoginCallback"
};
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
// comma separated
string scope = string.Join(",", Options.Scope);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&response_type=" + Uri.EscapeDataString(scope) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new ArcGISOnlineReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,16 +0,0 @@
using System;
namespace Owin.Security.Providers.ArcGISOnline.Provider
{
public class ArcGISOnlineUser
{
public User user { get; set; }
}
public class User
{
public string username { get; set; }
public string fullName { get; set; }
public string email { get; set; }
}
}

View File

@@ -1,288 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.BattleNet
{
public class BattleNetAuthenticationHandler : AuthenticationHandler<BattleNetAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly string _tokenEndpoint = "https://eu.battle.net/oauth/token";
private readonly string _accountUserIdEndpoint = "https://eu.api.battle.net/account/user/id";
private readonly string _accountUserBattleTagEndpoint = "https://eu.api.battle.net/account/user/battletag";
private readonly string _oauthAuthEndpoint = "https://eu.battle.net/oauth/authorize";
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public BattleNetAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
_httpClient = httpClient;
_logger = logger;
switch (Options.Region)
{
case Region.China:
_tokenEndpoint = "https://cn.battle.net/oauth/token";
_accountUserIdEndpoint = "https://cn.api.battle.net/account/user/id";
_accountUserBattleTagEndpoint = "https://cn.api.battle.net/account/user/battletag";
_oauthAuthEndpoint = "https://cn.battle.net/oauth/authorize";
break;
case Region.Korea:
_tokenEndpoint = "https://kr.battle.net/oauth/token";
_accountUserIdEndpoint = "https://kr.api.battle.net/account/user/id";
_accountUserBattleTagEndpoint = "https://kr.api.battle.net/account/user/battletag";
_oauthAuthEndpoint = "https://kr.battle.net/oauth/authorize";
break;
case Region.Taiwan:
_tokenEndpoint = "https://tw.battle.net/oauth/token";
_accountUserIdEndpoint = "https://tw.api.battle.net/account/user/id";
_accountUserBattleTagEndpoint = "https://tw.api.battle.net/account/user/battletag";
_oauthAuthEndpoint = "https://tw.battle.net/oauth/authorize";
break;
case Region.Europe:
_tokenEndpoint = "https://eu.battle.net/oauth/token";
_accountUserIdEndpoint = "https://eu.api.battle.net/account/user/id";
_accountUserBattleTagEndpoint = "https://eu.api.battle.net/account/user/battletag";
_oauthAuthEndpoint = "https://eu.battle.net/oauth/authorize";
break;
default:
_tokenEndpoint = "https://us.battle.net/oauth/token";
_accountUserIdEndpoint = "https://us.api.battle.net/account/user/id";
_accountUserBattleTagEndpoint = "https://us.api.battle.net/account/user/battletag";
_oauthAuthEndpoint = "https://us.battle.net/oauth/authorize";
break;
}
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
var query = Request.Query;
var values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, _logger))
{
return new AuthenticationTicket(null, properties);
}
// Check for error
if (Request.Query.Get("error") != null)
return new AuthenticationTicket(null, properties);
var requestPrefix = Request.Scheme + "://" + Request.Host;
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
new KeyValuePair<string, string>("client_id", Options.ClientId),
new KeyValuePair<string, string>("client_secret", Options.ClientSecret)
};
// Request the token
var tokenResponse = await _httpClient.PostAsync(_tokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
var text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
var response = JsonConvert.DeserializeObject<dynamic>(text);
var accessToken = (string)response.access_token;
var expires = (string)response.expires_in;
// Get WoW User Id
var graphResponse = await _httpClient.GetAsync(_accountUserIdEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
var userId = JObject.Parse(text);
// Get WoW BattleTag
graphResponse = await _httpClient.GetAsync(_accountUserBattleTagEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
var battleTag = JObject.Parse(text);
var context = new BattleNetAuthenticatedContext(Context, userId, battleTag, accessToken, expires)
{
Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType)
};
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.BattleTag))
{
context.Identity.AddClaim(new Claim("urn:battlenet:battletag", context.BattleTag, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:battlenet:accesstoken", context.AccessToken, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
_logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
var baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
var currentUri =
baseUri +
Request.Path +
Request.QueryString;
var redirectUri =
baseUri +
Options.CallbackPath;
var properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
var scope = string.Join(" ", Options.Scope);
var state = Options.StateDataFormat.Protect(properties);
var authorizationEndpoint =
_oauthAuthEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
var ticket = await AuthenticateAsync();
if (ticket == null)
{
_logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new BattleNetReturnEndpointContext(Context, ticket)
{
SignInAsAuthenticationType = Options.SignInAsAuthenticationType,
RedirectUri = ticket.Properties.RedirectUri
};
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,222 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.Buffer
{
public class BufferAuthenticationHandler : AuthenticationHandler<BufferAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://api.bufferapp.com/1/oauth2/token.json";
private const string UserInfoEndpoint = "https://api.bufferapp.com/1/user.json";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public BufferAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
// Get the Buffer user
HttpResponseMessage graphResponse = await httpClient.GetAsync(
UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new BufferAuthenticatedContext(Context, user, accessToken, expires);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://bufferapp.com/oauth2/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new BufferReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,229 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.Dropbox
{
public class DropboxAuthenticationHandler : AuthenticationHandler<DropboxAuthenticationOptions>
{
private const string StateCookie = "_DropboxState";
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://api.dropbox.com/1/oauth2/token";
private const string UserInfoEndpoint = "https://api.dropbox.com/1/account/info";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public DropboxAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
state = Request.Cookies[StateCookie];
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
// Check for error
if (Request.Query.Get("error") != null)
return new AuthenticationTicket(null, properties);
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.AppKey));
body.Add(new KeyValuePair<string, string>("client_secret", Options.AppSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the Dropbox user
HttpResponseMessage graphResponse = await httpClient.GetAsync(
UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new DropboxAuthenticatedContext(Context, user, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string authorizationEndpoint =
"https://www.dropbox.com/1/oauth2/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.AppKey) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri);
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Secure = Request.IsSecure
};
Response.StatusCode = 302;
Response.Cookies.Append(StateCookie, Options.StateDataFormat.Protect(properties), cookieOptions);
Response.Headers.Set("Location", authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new DropboxReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,237 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.GitHub
{
public class GitHubAuthenticationHandler : AuthenticationHandler<GitHubAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public GitHubAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the GitHub user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new GitHubAuthenticatedContext(Context, user, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim("urn:github:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:github:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new GitHubReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,259 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.GooglePlus.Provider;
namespace Owin.Security.Providers.GooglePlus
{
public class GooglePlusAuthenticationHandler : AuthenticationHandler<GooglePlusAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://accounts.google.com/o/oauth2/token";
private const string UserInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo";
private const string GooglePlusUserEndpoint = "https://www.googleapis.com/plus/v1/people/me";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public GooglePlusAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
string refreshToken = null;
if (response.refresh_token != null)
refreshToken = (string) response.refresh_token;
// Get the Google user
HttpResponseMessage graphResponse = await httpClient.GetAsync(
UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
// Get the Google+ Person Info
graphResponse = await httpClient.GetAsync(
GooglePlusUserEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject person = JObject.Parse(text);
var context = new GooglePlusAuthenticatedContext(Context, user, person, accessToken, expires, refreshToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim("urn:googleplus:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:googleplus:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(" ", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://accounts.google.com/o/oauth2/auth" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state);
// Check if offline access was requested
if (Options.RequestOfflineAccess)
authorizationEndpoint += "&access_type=offline";
// Request the moment types
if (Options.MomentTypes.Count > 0)
authorizationEndpoint += String.Format("&request_visible_actions={0}",
String.Join(" ", Options.MomentTypes));
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new GooglePlusReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,234 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.HealthGraph.Provider;
namespace Owin.Security.Providers.HealthGraph
{
public class HealthGraphAuthenticationHandler : AuthenticationHandler<HealthGraphAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private HttpClient httpClient;
private ILogger logger;
public HealthGraphAuthenticationHandler(
HttpClient httpClient,
ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected async override Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the RunKeeper user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
var userText = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(userText);
// Get the RunKeeper Profile
HttpRequestMessage profileRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.ProfileInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken));
HttpResponseMessage profileResponse = await httpClient.SendAsync(profileRequest, Request.CallCancelled);
profileResponse.EnsureSuccessStatusCode();
var profileText = await profileResponse.Content.ReadAsStringAsync();
JObject profile = JObject.Parse(profileText);
var context = new HealthGraphAuthenticatedContext(Context, user, profile, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.UserId))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.UserId, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&response_type=code" +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new HealthGraphReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,231 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.Instagram.Provider;
namespace Owin.Security.Providers.Instagram
{
public class InstagramAuthenticationHandler : AuthenticationHandler<InstagramAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://api.instagram.com/oauth/access_token";
private readonly HttpClient httpClient;
private readonly ILogger logger;
public InstagramAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
JObject user = (JObject) response.user;
var context = new InstagramAuthenticatedContext(Context, user, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim("urn:instagram:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.ProfilePicture))
{
context.Identity.AddClaim(new Claim("urn:instagram:profilepicture", context.ProfilePicture, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:instagram:accesstoken", context.AccessToken, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// plus separated (do not URL encode)
string scope = string.Join("+", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://api.instagram.com/oauth/authorize/" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + scope +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new InstagramReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,249 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.LinkedIn
{
public class LinkedInAuthenticationHandler : AuthenticationHandler<LinkedInAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://www.linkedin.com/uas/oauth2/accessToken";
private const string UserInfoEndpoint = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,formatted-name,email-address,public-profile-url,picture-url)";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public LinkedInAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
// Get the LinkedIn user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, UserInfoEndpoint + "?oauth2_access_token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Add("x-li-format", "json");
HttpResponseMessage graphResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new LinkedInAuthenticatedContext(Context, user, accessToken, expires);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim("urn:linkedin:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:linkedin:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:linkedin:accesstoken", context.AccessToken, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
// allow scopes to be specified via the authentication properties for this request, when specified they will already be comma separated
if (properties.Dictionary.ContainsKey("scope"))
{
scope = properties.Dictionary["scope"];
}
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://www.linkedin.com/uas/oauth2/authorization" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new LinkedInReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,8 +0,0 @@

namespace Owin.Security.Providers.OpenID
{
internal static class Constants
{
internal const string DefaultAuthenticationType = "OpenID";
}
}

View File

@@ -1,116 +0,0 @@
using Microsoft.Owin;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Properties;
using System;
using System.Globalization;
using System.Net.Http;
namespace Owin.Security.Providers.OpenID
{
/// <summary>
/// OWIN middleware for authenticating users using an OpenID provider
/// </summary>
public class OpenIDAuthenticationMiddleware : OpenIDAuthenticationMiddlewareBase<OpenIDAuthenticationOptions>
{
/// <summary>
/// Initializes a <see cref="OpenIDAuthenticationMiddleware"/>
/// </summary>
/// <param name="next">The next middleware in the OWIN pipeline to invoke</param>
/// <param name="app">The OWIN application</param>
/// <param name="options">Configuration options for the middleware</param>
public OpenIDAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app, OpenIDAuthenticationOptions options)
: base(next, app, options)
{ }
protected override AuthenticationHandler<OpenIDAuthenticationOptions> CreateSpecificHandler()
{
return new OpenIDAuthenticationHandler(_httpClient, _logger);
}
}
/// <summary>
/// OWIN middleware for authenticating users using an OpenID provider
/// </summary>
public abstract class OpenIDAuthenticationMiddlewareBase<T> : AuthenticationMiddleware<T> where T : OpenIDAuthenticationOptions
{
protected readonly ILogger _logger;
protected readonly HttpClient _httpClient;
/// <summary>
/// Initializes a <see cref="OpenIDAuthenticationMiddlewareBase"/>
/// </summary>
/// <param name="next">The next middleware in the OWIN pipeline to invoke</param>
/// <param name="app">The OWIN application</param>
/// <param name="options">Configuration options for the middleware</param>
public OpenIDAuthenticationMiddlewareBase(OwinMiddleware next, IAppBuilder app, T options)
: base(next, options)
{
if (String.IsNullOrWhiteSpace(Options.ProviderDiscoveryUri) && String.IsNullOrWhiteSpace(Options.ProviderLoginUri) && Options.AuthenticationType != Constants.DefaultAuthenticationType)
{
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "ProviderDiscoveryUri"));
}
_logger = app.CreateLogger<OpenIDAuthenticationMiddleware>();
if (Options.Provider == null)
{
Options.Provider = new OpenIDAuthenticationProvider();
}
if (Options.StateDataFormat == null)
{
IDataProtector dataProtecter = app.CreateDataProtector(
typeof(OpenIDAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtecter);
}
if (String.IsNullOrEmpty(Options.SignInAsAuthenticationType))
{
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
}
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options));
_httpClient.Timeout = Options.BackchannelTimeout;
_httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
}
/// <summary>
/// Provides the <see cref="AuthenticationHandler"/> object for processing authentication-related requests.
/// </summary>
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OpenIDAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<T> CreateHandler()
{
return CreateSpecificHandler();
}
/// <summary>
/// Provides the <see cref="AuthenticationHandler"/> object for processing authentication-related requests.
/// </summary>
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OpenIDAuthenticationOptions"/> supplied to the constructor.</returns>
protected abstract AuthenticationHandler<T> CreateSpecificHandler();
private static HttpMessageHandler ResolveHttpMessageHandler(OpenIDAuthenticationOptions options)
{
HttpMessageHandler handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator != null)
{
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
}
return handler;
}
}
}

View File

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Owin.Security.Providers.OpenID
{
public class OpenIDAuthorizationEndpointInfo
{
public string Url { get; set; }
}
}

View File

@@ -1,305 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers</RootNamespace>
<AssemblyName>Owin.Security.Providers</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArcGISOnline\ArcGISOnlineAuthenticationExtensions.cs" />
<Compile Include="ArcGISOnline\ArcGISOnlineAuthenticationHandler.cs" />
<Compile Include="ArcGISOnline\ArcGISOnlineAuthenticationMiddleware.cs" />
<Compile Include="ArcGISOnline\ArcGISOnlineAuthenticationOptions.cs" />
<Compile Include="ArcGISOnline\Constants.cs" />
<Compile Include="ArcGISOnline\Provider\ArcGISOnlineAuthenticatedContext.cs" />
<Compile Include="ArcGISOnline\Provider\ArcGISOnlineAuthenticationProvider.cs" />
<Compile Include="ArcGISOnline\Provider\ArcGISOnlineReturnEndpointContext.cs" />
<Compile Include="ArcGISOnline\Provider\ArcGISOnlineUser.cs" />
<Compile Include="ArcGISOnline\Provider\IArcGISOnlineAuthenticationProvider.cs" />
<Compile Include="Asana\AsanaAuthenticationExtensions.cs" />
<Compile Include="Asana\AsanaAuthenticationHandler.cs" />
<Compile Include="Asana\AsanaAuthenticationMiddleware.cs" />
<Compile Include="Asana\AsanaAuthenticationOptions.cs" />
<Compile Include="Asana\Constants.cs" />
<Compile Include="Asana\Provider\AsanaAuthenticatedContext.cs" />
<Compile Include="Asana\Provider\AsanaAuthenticationProvider.cs" />
<Compile Include="Asana\Provider\AsanaReturnEndpointContext.cs" />
<Compile Include="Asana\Provider\IAsanaAuthenticationProvider.cs" />
<Compile Include="BattleNet\BattleNetAuthenticationExtensions.cs" />
<Compile Include="BattleNet\BattleNetAuthenticationHandler.cs" />
<Compile Include="BattleNet\BattleNetAuthenticationMiddleware.cs" />
<Compile Include="BattleNet\BattleNetAuthenticationOptions.cs" />
<Compile Include="BattleNet\Provider\BattleNetAuthenticatedContext.cs" />
<Compile Include="BattleNet\Provider\BattleNetAuthenticationProvider.cs" />
<Compile Include="BattleNet\Provider\BattleNetReturnEndpointContext.cs" />
<Compile Include="BattleNet\Provider\IBattleNetAuthenticationProvider.cs" />
<Compile Include="Buffer\BufferAuthenticationExtensions.cs" />
<Compile Include="Buffer\BufferAuthenticationHandler.cs" />
<Compile Include="Buffer\BufferAuthenticationMiddleware.cs" />
<Compile Include="Buffer\BufferAuthenticationOptions.cs" />
<Compile Include="Buffer\Constants.cs" />
<Compile Include="Buffer\Provider\BufferAuthenticatedContext.cs" />
<Compile Include="Buffer\Provider\BufferAuthenticationProvider.cs" />
<Compile Include="Buffer\Provider\BufferReturnEndpointContext.cs" />
<Compile Include="Buffer\Provider\IBufferAuthenticationProvider.cs" />
<Compile Include="BattleNet\Constants.cs" />
<Compile Include="Dropbox\DropboxAuthenticationExtensions.cs" />
<Compile Include="Dropbox\DropboxAuthenticationHandler.cs" />
<Compile Include="Dropbox\DropboxAuthenticationMiddleware.cs" />
<Compile Include="Dropbox\DropboxAuthenticationOptions.cs" />
<Compile Include="Dropbox\Constants.cs" />
<Compile Include="Dropbox\Provider\DropboxAuthenticatedContext.cs" />
<Compile Include="Dropbox\Provider\DropboxAuthenticationProvider.cs" />
<Compile Include="Dropbox\Provider\DropboxReturnEndpointContext.cs" />
<Compile Include="Dropbox\Provider\IDropboxAuthenticationProvider.cs" />
<Compile Include="EveOnline\EveOnlineAuthenticationExtensions.cs" />
<Compile Include="EveOnline\EveOnlineAuthenticationHandler.cs" />
<Compile Include="EveOnline\EveOnlineAuthenticationMiddleware.cs" />
<Compile Include="EveOnline\EveOnlineAuthenticationOptions.cs" />
<Compile Include="EveOnline\Constants.cs" />
<Compile Include="EveOnline\Provider\EveOnlineAuthenticatedContext.cs" />
<Compile Include="EveOnline\Provider\EveOnlineAuthenticationProvider.cs" />
<Compile Include="EveOnline\Provider\EveOnlineReturnEndpointContext.cs" />
<Compile Include="EveOnline\Provider\IEveOnlineAuthenticationProvider.cs" />
<Compile Include="Foursquare\Constants.cs" />
<Compile Include="Foursquare\FoursquareAuthenticationExtensions.cs" />
<Compile Include="Foursquare\FoursquareAuthenticationHandler.cs" />
<Compile Include="Foursquare\FoursquareAuthenticationMiddleware.cs" />
<Compile Include="Foursquare\FoursquareAuthenticationOptions.cs" />
<Compile Include="Foursquare\Provider\FoursquareAuthenticatedContext.cs" />
<Compile Include="Foursquare\Provider\FoursquareAuthenticationProvider.cs" />
<Compile Include="Foursquare\Provider\FoursquareReturnEndpointContext.cs" />
<Compile Include="Foursquare\Provider\IFoursquareAuthenticationProvider.cs" />
<Compile Include="GitHub\Constants.cs" />
<Compile Include="HealthGraph\Constants.cs" />
<Compile Include="GitHub\GitHubAuthenticationExtensions.cs" />
<Compile Include="GitHub\GitHubAuthenticationHandler.cs" />
<Compile Include="GitHub\GitHubAuthenticationMiddleware.cs" />
<Compile Include="GitHub\GitHubAuthenticationOptions.cs" />
<Compile Include="GitHub\Provider\IGitHubAuthenticationProvider.cs" />
<Compile Include="GitHub\Provider\GitHubAuthenticatedContext.cs" />
<Compile Include="GitHub\Provider\GitHubAuthenticationProvider.cs" />
<Compile Include="GitHub\Provider\GitHubReturnEndpointContext.cs" />
<Compile Include="GooglePlus\Constants.cs" />
<Compile Include="GooglePlus\GooglePlusAuthenticationExtensions.cs" />
<Compile Include="GooglePlus\GooglePlusAuthenticationHandler.cs" />
<Compile Include="GooglePlus\GooglePlusAuthenticationMiddleware.cs" />
<Compile Include="GooglePlus\GooglePlusAuthenticationOptions.cs" />
<Compile Include="GooglePlus\Provider\GooglePlusAuthenticatedContext.cs" />
<Compile Include="GooglePlus\Provider\GooglePlusAuthenticationProvider.cs" />
<Compile Include="GooglePlus\Provider\GooglePlusReturnEndpointContext.cs" />
<Compile Include="GooglePlus\Provider\IGooglePlusAuthenticationProvider.cs" />
<Compile Include="HealthGraph\HealthGraphAuthenticationExtensions.cs" />
<Compile Include="HealthGraph\HealthGraphAuthenticationHandler.cs" />
<Compile Include="HealthGraph\HealthGraphAuthenticationMiddleware.cs" />
<Compile Include="HealthGraph\Provider\HealthGraphAuthenticatedContext.cs" />
<Compile Include="HealthGraph\Provider\HealthGraphAuthenticationProvider.cs" />
<Compile Include="HealthGraph\Provider\HealthGraphReturnEndpointContext.cs" />
<Compile Include="HealthGraph\Provider\IHealthGraphAuthenticationProvider.cs" />
<Compile Include="Instagram\Constants.cs" />
<Compile Include="Instagram\InstagramAuthenticationExtensions.cs" />
<Compile Include="Instagram\InstagramAuthenticationHandler.cs" />
<Compile Include="Instagram\InstagramAuthenticationMiddleware.cs" />
<Compile Include="Instagram\InstagramAuthenticationOptions.cs" />
<Compile Include="Instagram\Provider\IInstagramAuthenticationProvider.cs" />
<Compile Include="Instagram\Provider\InstagramAuthenticatedContext.cs" />
<Compile Include="Instagram\Provider\InstagramAuthenticationProvider.cs" />
<Compile Include="Instagram\Provider\InstagramReturnEndpointContext.cs" />
<Compile Include="LinkedIn\Constants.cs" />
<Compile Include="LinkedIn\LinkedInAuthenticationExtensions.cs" />
<Compile Include="LinkedIn\LinkedInAuthenticationHandler.cs" />
<Compile Include="LinkedIn\LinkedInAuthenticationMiddleware.cs" />
<Compile Include="LinkedIn\LinkedInAuthenticationOptions.cs" />
<Compile Include="LinkedIn\Provider\LinkedInAuthenticatedContext.cs" />
<Compile Include="LinkedIn\Provider\LinkedInAuthenticationProvider.cs" />
<Compile Include="LinkedIn\Provider\LinkedInReturnEndpointContext.cs" />
<Compile Include="LinkedIn\Provider\ILinkedInAuthenticationProvider.cs" />
<Compile Include="OpenID\Constants.cs" />
<Compile Include="OpenID\Extensions\OpenIDSimpleRegistrationAuthenticationContextExtensions.cs" />
<Compile Include="OpenID\Extensions\OpenIDSimpleRegistrationExtension.cs" />
<Compile Include="OpenID\Extensions\OpenIDSimpleRegistrationResult.cs" />
<Compile Include="OpenID\Extensions\OpenIDSimpleRegistrationField.cs" />
<Compile Include="OpenID\Infrastructure\Message.cs" />
<Compile Include="OpenID\Infrastructure\Property.cs" />
<Compile Include="OpenID\IOpenIDProtocolExtension.cs" />
<Compile Include="OpenID\OpenIDAuthenticationExtensions.cs" />
<Compile Include="OpenID\OpenIDAuthenticationHandler.cs" />
<Compile Include="OpenID\OpenIDAuthenticationMiddleware.cs" />
<Compile Include="OpenID\OpenIDAuthenticationOptions.cs" />
<Compile Include="OpenID\OpenIDAuthorizationEndpointInfo.cs" />
<Compile Include="OpenID\Provider\IOpenIDAuthenticationProvider.cs" />
<Compile Include="OpenID\Provider\OpenIDAuthenticatedContext.cs" />
<Compile Include="OpenID\Provider\OpenIDAuthenticationProvider.cs" />
<Compile Include="OpenID\Provider\OpenIDReturnEndpointContext.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Reddit\Constants.cs" />
<Compile Include="Reddit\Provider\IRedditAuthenticationProvider.cs" />
<Compile Include="Reddit\Provider\RedditAuthenticatedContext.cs" />
<Compile Include="Reddit\Provider\RedditAuthenticationProvider.cs" />
<Compile Include="Reddit\Provider\RedditReturnEndpointContext.cs" />
<Compile Include="Reddit\RedditAuthenticationExtensions.cs" />
<Compile Include="Reddit\RedditAuthenticationHandler.cs" />
<Compile Include="Reddit\RedditAuthenticationMiddleware.cs" />
<Compile Include="Reddit\RedditAuthenticationOptions.cs" />
<Compile Include="HealthGraph\HealthGraphAuthenticationOptions.cs" />
<Compile Include="Salesforce\Constants.cs" />
<Compile Include="Salesforce\Provider\ISalesforceAuthenticationProvider.cs" />
<Compile Include="Salesforce\Provider\SalesforceAuthenticatedContext.cs" />
<Compile Include="Salesforce\Provider\SalesforceAuthenticationProvider.cs" />
<Compile Include="Salesforce\Provider\SalesforceReturnEndpointContext.cs" />
<Compile Include="Salesforce\SalesforceAuthenticationExtensions.cs" />
<Compile Include="Salesforce\SalesforceAuthenticationHandler.cs" />
<Compile Include="Salesforce\SalesforceAuthenticationMiddleware.cs" />
<Compile Include="Salesforce\SalesforceAuthenticationOptions.cs" />
<Compile Include="SoundCloud\Constants.cs" />
<Compile Include="SoundCloud\Provider\ISoundCloudAuthenticationProvider.cs" />
<Compile Include="SoundCloud\Provider\SoundCloudAuthenticatedContext.cs" />
<Compile Include="SoundCloud\Provider\SoundCloudAuthenticationProvider.cs" />
<Compile Include="SoundCloud\Provider\SoundCloudReturnEndpointContext.cs" />
<Compile Include="SoundCloud\SoundCloudAuthenticationExtensions.cs" />
<Compile Include="SoundCloud\SoundCloudAuthenticationHandler.cs" />
<Compile Include="SoundCloud\SoundCloudAuthenticationMiddleware.cs" />
<Compile Include="SoundCloud\SoundCloudAuthenticationOptions.cs" />
<Compile Include="StackExchange\Constants.cs" />
<Compile Include="StackExchange\StackExchangeAuthenticationExtensions.cs" />
<Compile Include="StackExchange\StackExchangeAuthenticationHandler.cs" />
<Compile Include="StackExchange\StackExchangeAuthenticationMiddleware.cs" />
<Compile Include="StackExchange\StackExchangeAuthenticationOptions.cs" />
<Compile Include="StackExchange\Provider\IStackExchangeAuthenticationProvider.cs" />
<Compile Include="StackExchange\Provider\StackExchangeAuthenticatedContext.cs" />
<Compile Include="StackExchange\Provider\StackExchangeAuthenticationProvider.cs" />
<Compile Include="StackExchange\Provider\StackExchangeReturnEndpointContext.cs" />
<Compile Include="Steam\SteamAuthenticationExtensions.cs" />
<Compile Include="Steam\SteamAuthenticationHandler.cs" />
<Compile Include="Steam\SteamAuthenticationMiddleware.cs" />
<Compile Include="Steam\SteamAuthenticationOptions.cs" />
<Compile Include="TripIt\Constants.cs" />
<Compile Include="TripIt\Messages\AccessToken.cs" />
<Compile Include="TripIt\Messages\RequestToken.cs" />
<Compile Include="TripIt\Messages\RequestTokenSerializer.cs" />
<Compile Include="TripIt\Messages\Serializers.cs" />
<Compile Include="TripIt\Provider\ITripItAuthenticationProvider.cs" />
<Compile Include="TripIt\Provider\TripItAuthenticatedContext.cs" />
<Compile Include="TripIt\Provider\TripItAuthenticationProvider.cs" />
<Compile Include="TripIt\Provider\TripItReturnEndpointContext.cs" />
<Compile Include="TripIt\TripItAuthenticationExtensions.cs" />
<Compile Include="TripIt\TripItAuthenticationHandler.cs" />
<Compile Include="TripIt\TripItAuthenticationMiddleware.cs" />
<Compile Include="TripIt\TripItAuthenticationOptions.cs" />
<Compile Include="Twitch\Constants.cs" />
<Compile Include="Twitch\TwitchAuthenticationExtensions.cs" />
<Compile Include="Twitch\TwitchAuthenticationHandler.cs" />
<Compile Include="Twitch\TwitchAuthenticationMiddleware.cs" />
<Compile Include="Twitch\TwitchAuthenticationOptions.cs" />
<Compile Include="Twitch\Provider\TwitchAuthenticatedContext.cs" />
<Compile Include="Twitch\Provider\TwitchAuthenticationProvider.cs" />
<Compile Include="Twitch\Provider\TwitchReturnEndpointContext.cs" />
<Compile Include="Twitch\Provider\ITwitchAuthenticationProvider.cs" />
<Compile Include="WordPress\WordPressAuthenticationExtensions.cs" />
<Compile Include="WordPress\WordPressAuthenticationHandler.cs" />
<Compile Include="WordPress\WordPressAuthenticationMiddleware.cs" />
<Compile Include="WordPress\WordPressAuthenticationOptions.cs" />
<Compile Include="WordPress\Constants.cs" />
<Compile Include="WordPress\Provider\WordPressAuthenticatedContext.cs" />
<Compile Include="WordPress\Provider\WordPressAuthenticationProvider.cs" />
<Compile Include="WordPress\Provider\WordPressReturnEndpointContext.cs" />
<Compile Include="WordPress\Provider\IWordPressAuthenticationProvider.cs" />
<Compile Include="Yahoo\Constants.cs" />
<Compile Include="Yahoo\Messages\AccessToken.cs" />
<Compile Include="Yahoo\Messages\RequestToken.cs" />
<Compile Include="Yahoo\Messages\RequestTokenSerializer.cs" />
<Compile Include="Yahoo\Messages\Serializers.cs" />
<Compile Include="Yahoo\Provider\IYahooAuthenticationProvider.cs" />
<Compile Include="Yahoo\Provider\YahooAuthenticatedContext.cs" />
<Compile Include="Yahoo\Provider\YahooAuthenticationProvider.cs" />
<Compile Include="Yahoo\Provider\YahooReturnEndpointContext.cs" />
<Compile Include="Yahoo\YahooAuthenticationExtensions.cs" />
<Compile Include="Yahoo\YahooAuthenticationHandler.cs" />
<Compile Include="Yahoo\YahooAuthenticationMiddleware.cs" />
<Compile Include="Yahoo\YahooAuthenticationOptions.cs" />
<Compile Include="Yammer\Constants.cs" />
<Compile Include="Yammer\Provider\IYammerAuthenticationProvider.cs" />
<Compile Include="Yammer\Provider\YammerAuthenticatedContext.cs" />
<Compile Include="Yammer\Provider\YammerAuthenticationProvider.cs" />
<Compile Include="Yammer\Provider\YammerReturnEndpointContext.cs" />
<Compile Include="Yammer\YammerAuthenticationHandler.cs" />
<Compile Include="Yammer\YammerAuthenticationExtensions.cs" />
<Compile Include="Yammer\YammerAuthenticationMiddleware.cs" />
<Compile Include="Yammer\YammerAuthenticationOptions.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,7 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=BattleNet_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=Buffer_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=DropBox_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=Dropbox_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=GitHub_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=WordPress_005CProvider/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Owin.Security.Providers")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c745499f-213a-461d-9dfb-c46935ec44e9")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.16.0.0")]
[assembly: AssemblyFileVersion("1.16.0.0")]

View File

@@ -1,245 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.Reddit.Provider;
namespace Owin.Security.Providers.Reddit
{
public class RedditAuthenticationHandler : AuthenticationHandler<RedditAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://ssl.reddit.com/api/v1/access_token";
private const string UserInfoEndpoint = "https://oauth.reddit.com/api/v1/me";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public RedditAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("state", state));
body.Add(new KeyValuePair<string, string>("scope", string.Join(",", Options.Scope)));
var request = new HttpRequestMessage(HttpMethod.Post, TokenEndpoint);
request.Content = new FormUrlEncodedContent(body);
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
string refreshToken = (string) response.refresh_token;
// Get the Reddit user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, UserInfoEndpoint);
userRequest.Headers.Add("User-Agent", "OWIN OAuth Provider");
userRequest.Headers.Add("Authorization", "bearer " + Uri.EscapeDataString(accessToken) + "");
HttpResponseMessage graphResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new RedditAuthenticatedContext(Context, user, accessToken, expires, refreshToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:reddit:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:reddit:accesstoken", context.AccessToken, XmlSchemaString, Options.AuthenticationType));
}
context.Identity.AddClaim(new Claim("urn:reddit:overeighteen", context.OverEighteen.ToString()));
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://ssl.reddit.com/api/v1/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state) +
"&duration=permanent";
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new RedditReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,36 +0,0 @@
using Microsoft.Owin.Logging;
using Newtonsoft.Json;
using Owin.Security.Providers.OpenID;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Text.RegularExpressions;
namespace Owin.Security.Providers.Steam
{
internal sealed class SteamAuthenticationHandler : OpenIDAuthenticationHandlerBase<SteamAuthenticationOptions>
{
private readonly Regex AccountIDRegex = new Regex(@"^http://steamcommunity\.com/openid/id/(7[0-9]{15,25})$", RegexOptions.Compiled);
private const string UserInfoUri = "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={0}&steamids={1}";
public SteamAuthenticationHandler(HttpClient httpClient, ILogger logger)
: base(httpClient, logger)
{ }
protected override void SetIdentityInformations(ClaimsIdentity identity, string claimedID, IDictionary<string, string> attributeExchangeProperties)
{
Match accountIDMatch = AccountIDRegex.Match(claimedID);
if (accountIDMatch.Success)
{
string accountID = accountIDMatch.Groups[1].Value;
var getUserInfoTask = _httpClient.GetStringAsync(string.Format(UserInfoUri, Options.ApplicationKey, accountID));
getUserInfoTask.Wait();
string userInfoRaw = getUserInfoTask.Result;
dynamic userInfo = JsonConvert.DeserializeObject<dynamic>(userInfoRaw);
identity.AddClaim(new Claim(ClaimTypes.Name, (string)userInfo.response.players[0].personaname, "http://www.w3.org/2001/XMLSchema#string", Options.AuthenticationType));
}
}
}
}

View File

@@ -1,9 +0,0 @@
using Owin.Security.Providers.OpenID;
namespace Owin.Security.Providers.Steam
{
public sealed class SteamAuthenticationOptions : OpenIDAuthenticationOptions
{
public string ApplicationKey { get; set; }
}
}

View File

@@ -1,241 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.Twitch
{
public class TwitchAuthenticationHandler : AuthenticationHandler<TwitchAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public TwitchAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = string.Copy(values.First());
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("code", code));
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Content = new FormUrlEncodedContent(body);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the Twitch user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?oauth_token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new TwitchAuthenticatedContext(Context, user, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim("urn:Twitch:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:Twitch:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(" ", Options.Scope.Distinct());
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&response_type=" + "code" +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new TwitchReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,239 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.WordPress
{
public class WordPressAuthenticationHandler : AuthenticationHandler<WordPressAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://public-api.wordpress.com/oauth2/token";
private const string UserInfoEndpoint = "https://public-api.wordpress.com/rest/v1/me";
private const string SiteInfoEndpoint = "https://public-api.wordpress.com/rest/v1/sites/";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public WordPressAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string blogId = (string)response.blog_id;
string blogUrl = (string)response.blog_url;
// Get the Wordpress user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, UserInfoEndpoint);
userRequest.Headers.Add("User-Agent", "OWIN OAuth Provider");
userRequest.Headers.Add("Authorization", "BEARER " + accessToken);
HttpResponseMessage graphResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
// Get the site details
HttpRequestMessage siteRequest = new HttpRequestMessage(HttpMethod.Get, SiteInfoEndpoint + blogId);
siteRequest.Headers.Add("User-Agent", "OWIN OAuth Provider");
siteRequest.Headers.Add("Authorization", "BEARER " + accessToken);
HttpResponseMessage siteResponse = await httpClient.SendAsync(siteRequest, Request.CallCancelled);
siteResponse.EnsureSuccessStatusCode();
text = await siteResponse.Content.ReadAsStringAsync();
JObject site = JObject.Parse(text);
var context = new WordPressAuthenticatedContext(Context, user, site, accessToken, blogId, blogUrl);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://public-api.wordpress.com/oauth2/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new WordPressReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
}
}

View File

@@ -1,250 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.Yammer.Provider;
namespace Owin.Security.Providers.Yammer
{
public class YammerAuthenticationHandler : AuthenticationHandler<YammerAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://www.yammer.com/oauth2/access_token.json";
private const string UserAuthenticationEndpoint = "https://www.yammer.com/dialog/oauth";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public YammerAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
if (code == null)
{
throw new Exception(query["error"] + " - " + query["error_description"]);
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
string endPoint =
TokenEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&client_secret=" + Uri.EscapeDataString(Options.ClientSecret) +
"&code=" + Uri.EscapeDataString(code);
// Request the token
HttpResponseMessage tokenResponse = await httpClient.GetAsync(endPoint);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token.token;
// Get the Yammer user
dynamic user = response.user;
var context = new YammerAuthenticatedContext(Context, user, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
EnsureAcceptedNetwork(Options.AcceptedNetworks, context.Network);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.PrimaryEmail))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.PrimaryEmail, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Url))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Uri, context.Url, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:Yammer:accesstoken", context.AccessToken, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
UserAuthenticationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new YammerReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
}
return false;
}
private void EnsureAcceptedNetwork(string[] validNetworks, string userNetwork)
{
if (validNetworks != null && validNetworks.Length > 0)
{
bool isValid = false;
foreach (string network in validNetworks)
{
if (userNetwork == network)
{
isValid = true;
break;
}
}
if (!isValid) throw new Exception("User is not in list of accepted networks");
}
}
}
}

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
</packages>

View File

@@ -1,11 +1,96 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30723.0
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OwinOAuthProvidersDemo", "OwinOAuthProvidersDemo\OwinOAuthProvidersDemo.csproj", "{5A438007-0C90-4DAC-BAA1-54A32164067F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers", "Owin.Security.Providers\Owin.Security.Providers.csproj", "{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.ArcGISOnline", "src\Owin.Security.Providers.ArcGISOnline\Owin.Security.Providers.ArcGISOnline.csproj", "{8A49FAEF-D365-4D25-942C-1CAD03845A5E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Asana", "src\Owin.Security.Providers.Asana\Owin.Security.Providers.Asana.csproj", "{F3E27220-1D8C-4037-94AA-7B7F4A12F351}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Backlog", "src\Owin.Security.Providers.Backlog\Owin.Security.Providers.Backlog.csproj", "{2DC03778-9EF1-466A-83EC-7D8422DECD23}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.BattleNet", "src\Owin.Security.Providers.BattleNet\Owin.Security.Providers.BattleNet.csproj", "{99A175DA-ADE4-436C-A272-C8AE44B7A086}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Bitbucket", "src\Owin.Security.Providers.Bitbucket\Owin.Security.Providers.Bitbucket.csproj", "{E5212FC7-ABCB-462F-9989-8E022DFFE43C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Buffer", "src\Owin.Security.Providers.Buffer\Owin.Security.Providers.Buffer.csproj", "{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Cosign", "src\Owin.Security.Providers.Cosign\Owin.Security.Providers.Cosign.csproj", "{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.DeviantArt", "src\Owin.Security.Providers.DeviantArt\Owin.Security.Providers.DeviantArt.csproj", "{FABD2E54-976D-41F5-8800-DEE58ACC027C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.DoYouBuzz", "src\Owin.Security.Providers.DoYouBuzz\Owin.Security.Providers.DoYouBuzz.csproj", "{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Dropbox", "src\Owin.Security.Providers.Dropbox\Owin.Security.Providers.Dropbox.csproj", "{CEF697B1-3651-49E5-9060-65F2E26C039C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.EVEOnline", "src\Owin.Security.Providers.EVEOnline\Owin.Security.Providers.EVEOnline.csproj", "{F5DC23F4-5042-4024-9E34-ACA648602BA0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Fitbit", "src\Owin.Security.Providers.Fitbit\Owin.Security.Providers.Fitbit.csproj", "{CA44D014-5A74-4749-A891-1F711FD3A266}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Flickr", "src\Owin.Security.Providers.Flickr\Owin.Security.Providers.Flickr.csproj", "{AF6CBEB8-5638-43D4-839E-C81F305960BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Foursquare", "src\Owin.Security.Providers.Foursquare\Owin.Security.Providers.Foursquare.csproj", "{8ACD9194-1EFE-4128-AC42-856D856332A4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.GitHub", "src\Owin.Security.Providers.GitHub\Owin.Security.Providers.GitHub.csproj", "{803F9EB7-029C-45AC-AB81-135E60D5BEAE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Gitter", "src\Owin.Security.Providers.Gitter\Owin.Security.Providers.Gitter.csproj", "{42EC50EB-0C51-460C-93A4-1E007BF1F323}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.GooglePlus", "src\Owin.Security.Providers.GooglePlus\Owin.Security.Providers.GooglePlus.csproj", "{D3FEF959-0E0E-4F50-954C-F123A0B629DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.HealthGraph", "src\Owin.Security.Providers.HealthGraph\Owin.Security.Providers.HealthGraph.csproj", "{157BB715-29B2-4202-8A59-CCBACFCBEDD3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Imgur", "src\Owin.Security.Providers.Imgur\Owin.Security.Providers.Imgur.csproj", "{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Instagram", "src\Owin.Security.Providers.Instagram\Owin.Security.Providers.Instagram.csproj", "{041178C4-6131-4D68-9896-CE33124D83A0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.LinkedIn", "src\Owin.Security.Providers.LinkedIn\Owin.Security.Providers.LinkedIn.csproj", "{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Onshape", "src\Owin.Security.Providers.Onshape\Owin.Security.Providers.Onshape.csproj", "{9FEC99F8-6F45-40A2-8200-85381434C79A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.OpenID", "src\Owin.Security.Providers.OpenID\Owin.Security.Providers.OpenID.csproj", "{90C152D7-9C66-4949-9998-C7CE48B593DE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.PayPal", "src\Owin.Security.Providers.PayPal\Owin.Security.Providers.PayPal.csproj", "{F7129064-3DB7-4B79-81D3-80130D664E45}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Reddit", "src\Owin.Security.Providers.Reddit\Owin.Security.Providers.Reddit.csproj", "{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Salesforce", "src\Owin.Security.Providers.Salesforce\Owin.Security.Providers.Salesforce.csproj", "{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Shopify", "src\Owin.Security.Providers.Shopify\Owin.Security.Providers.Shopify.csproj", "{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.SoundCloud", "src\Owin.Security.Providers.SoundCloud\Owin.Security.Providers.SoundCloud.csproj", "{2C959026-7058-4302-A6C4-DFD10A030585}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Spotify", "src\Owin.Security.Providers.Spotify\Owin.Security.Providers.Spotify.csproj", "{683B4041-A399-40CE-84B8-392F08A6805D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.StackExchange", "src\Owin.Security.Providers.StackExchange\Owin.Security.Providers.StackExchange.csproj", "{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Steam", "src\Owin.Security.Providers.Steam\Owin.Security.Providers.Steam.csproj", "{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.TripIt", "src\Owin.Security.Providers.TripIt\Owin.Security.Providers.TripIt.csproj", "{B35E2616-DC00-48B4-BD58-7E23046257F1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Twitch", "src\Owin.Security.Providers.Twitch\Owin.Security.Providers.Twitch.csproj", "{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Untappd", "src\Owin.Security.Providers.Untappd\Owin.Security.Providers.Untappd.csproj", "{3E89ECA3-F4E7-4181-B26B-8250D5151044}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Vimeo", "src\Owin.Security.Providers.Vimeo\Owin.Security.Providers.Vimeo.csproj", "{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.VisualStudio", "src\Owin.Security.Providers.VisualStudio\Owin.Security.Providers.VisualStudio.csproj", "{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.VKontakte", "src\Owin.Security.Providers.VKontakte\Owin.Security.Providers.VKontakte.csproj", "{32D70E31-3799-482A-AC7A-081FF9206FC3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Wargaming", "src\Owin.Security.Providers.Wargaming\Owin.Security.Providers.Wargaming.csproj", "{AA72BFCE-8495-4A4D-988D-F8D490521776}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.WordPress", "src\Owin.Security.Providers.WordPress\Owin.Security.Providers.WordPress.csproj", "{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Xing", "src\Owin.Security.Providers.Xing\Owin.Security.Providers.Xing.csproj", "{D497D8BD-6EF9-4C30-B195-B0DD153418D6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Yahoo", "src\Owin.Security.Providers.Yahoo\Owin.Security.Providers.Yahoo.csproj", "{1765BEDB-9E4B-468C-BAF6-06784CDCED67}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Yammer", "src\Owin.Security.Providers.Yammer\Owin.Security.Providers.Yammer.csproj", "{8D029A93-E687-4DDF-82B0-700EBBF477F7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.OpenIDBase", "base\Owin.Security.Providers.OpenIDBase\Owin.Security.Providers.OpenIDBase.csproj", "{4FD7B873-1994-4990-AA40-C37060121494}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.SlackProvider", "src\Owin.Security.Providers.SlackProvider\Owin.Security.Providers.SlackProvider.csproj", "{3E6F293D-8500-428D-BDC9-27440CC91E16}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -17,10 +102,182 @@ Global
{5A438007-0C90-4DAC-BAA1-54A32164067F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A438007-0C90-4DAC-BAA1-54A32164067F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A438007-0C90-4DAC-BAA1-54A32164067F}.Release|Any CPU.Build.0 = Release|Any CPU
{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}.Release|Any CPU.Build.0 = Release|Any CPU
{8A49FAEF-D365-4D25-942C-1CAD03845A5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A49FAEF-D365-4D25-942C-1CAD03845A5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A49FAEF-D365-4D25-942C-1CAD03845A5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A49FAEF-D365-4D25-942C-1CAD03845A5E}.Release|Any CPU.Build.0 = Release|Any CPU
{F3E27220-1D8C-4037-94AA-7B7F4A12F351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3E27220-1D8C-4037-94AA-7B7F4A12F351}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3E27220-1D8C-4037-94AA-7B7F4A12F351}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3E27220-1D8C-4037-94AA-7B7F4A12F351}.Release|Any CPU.Build.0 = Release|Any CPU
{2DC03778-9EF1-466A-83EC-7D8422DECD23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2DC03778-9EF1-466A-83EC-7D8422DECD23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2DC03778-9EF1-466A-83EC-7D8422DECD23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2DC03778-9EF1-466A-83EC-7D8422DECD23}.Release|Any CPU.Build.0 = Release|Any CPU
{99A175DA-ADE4-436C-A272-C8AE44B7A086}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99A175DA-ADE4-436C-A272-C8AE44B7A086}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99A175DA-ADE4-436C-A272-C8AE44B7A086}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99A175DA-ADE4-436C-A272-C8AE44B7A086}.Release|Any CPU.Build.0 = Release|Any CPU
{E5212FC7-ABCB-462F-9989-8E022DFFE43C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5212FC7-ABCB-462F-9989-8E022DFFE43C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5212FC7-ABCB-462F-9989-8E022DFFE43C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5212FC7-ABCB-462F-9989-8E022DFFE43C}.Release|Any CPU.Build.0 = Release|Any CPU
{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}.Release|Any CPU.Build.0 = Release|Any CPU
{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}.Release|Any CPU.Build.0 = Release|Any CPU
{FABD2E54-976D-41F5-8800-DEE58ACC027C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FABD2E54-976D-41F5-8800-DEE58ACC027C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FABD2E54-976D-41F5-8800-DEE58ACC027C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FABD2E54-976D-41F5-8800-DEE58ACC027C}.Release|Any CPU.Build.0 = Release|Any CPU
{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}.Release|Any CPU.Build.0 = Release|Any CPU
{CEF697B1-3651-49E5-9060-65F2E26C039C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CEF697B1-3651-49E5-9060-65F2E26C039C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CEF697B1-3651-49E5-9060-65F2E26C039C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CEF697B1-3651-49E5-9060-65F2E26C039C}.Release|Any CPU.Build.0 = Release|Any CPU
{F5DC23F4-5042-4024-9E34-ACA648602BA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5DC23F4-5042-4024-9E34-ACA648602BA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5DC23F4-5042-4024-9E34-ACA648602BA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5DC23F4-5042-4024-9E34-ACA648602BA0}.Release|Any CPU.Build.0 = Release|Any CPU
{CA44D014-5A74-4749-A891-1F711FD3A266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA44D014-5A74-4749-A891-1F711FD3A266}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA44D014-5A74-4749-A891-1F711FD3A266}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA44D014-5A74-4749-A891-1F711FD3A266}.Release|Any CPU.Build.0 = Release|Any CPU
{AF6CBEB8-5638-43D4-839E-C81F305960BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF6CBEB8-5638-43D4-839E-C81F305960BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF6CBEB8-5638-43D4-839E-C81F305960BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF6CBEB8-5638-43D4-839E-C81F305960BE}.Release|Any CPU.Build.0 = Release|Any CPU
{8ACD9194-1EFE-4128-AC42-856D856332A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8ACD9194-1EFE-4128-AC42-856D856332A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8ACD9194-1EFE-4128-AC42-856D856332A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8ACD9194-1EFE-4128-AC42-856D856332A4}.Release|Any CPU.Build.0 = Release|Any CPU
{803F9EB7-029C-45AC-AB81-135E60D5BEAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{803F9EB7-029C-45AC-AB81-135E60D5BEAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{803F9EB7-029C-45AC-AB81-135E60D5BEAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{803F9EB7-029C-45AC-AB81-135E60D5BEAE}.Release|Any CPU.Build.0 = Release|Any CPU
{42EC50EB-0C51-460C-93A4-1E007BF1F323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42EC50EB-0C51-460C-93A4-1E007BF1F323}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42EC50EB-0C51-460C-93A4-1E007BF1F323}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42EC50EB-0C51-460C-93A4-1E007BF1F323}.Release|Any CPU.Build.0 = Release|Any CPU
{D3FEF959-0E0E-4F50-954C-F123A0B629DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3FEF959-0E0E-4F50-954C-F123A0B629DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3FEF959-0E0E-4F50-954C-F123A0B629DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3FEF959-0E0E-4F50-954C-F123A0B629DC}.Release|Any CPU.Build.0 = Release|Any CPU
{157BB715-29B2-4202-8A59-CCBACFCBEDD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{157BB715-29B2-4202-8A59-CCBACFCBEDD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{157BB715-29B2-4202-8A59-CCBACFCBEDD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{157BB715-29B2-4202-8A59-CCBACFCBEDD3}.Release|Any CPU.Build.0 = Release|Any CPU
{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}.Release|Any CPU.Build.0 = Release|Any CPU
{041178C4-6131-4D68-9896-CE33124D83A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{041178C4-6131-4D68-9896-CE33124D83A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{041178C4-6131-4D68-9896-CE33124D83A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{041178C4-6131-4D68-9896-CE33124D83A0}.Release|Any CPU.Build.0 = Release|Any CPU
{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}.Release|Any CPU.Build.0 = Release|Any CPU
{9FEC99F8-6F45-40A2-8200-85381434C79A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FEC99F8-6F45-40A2-8200-85381434C79A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FEC99F8-6F45-40A2-8200-85381434C79A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FEC99F8-6F45-40A2-8200-85381434C79A}.Release|Any CPU.Build.0 = Release|Any CPU
{90C152D7-9C66-4949-9998-C7CE48B593DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{90C152D7-9C66-4949-9998-C7CE48B593DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90C152D7-9C66-4949-9998-C7CE48B593DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90C152D7-9C66-4949-9998-C7CE48B593DE}.Release|Any CPU.Build.0 = Release|Any CPU
{F7129064-3DB7-4B79-81D3-80130D664E45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7129064-3DB7-4B79-81D3-80130D664E45}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7129064-3DB7-4B79-81D3-80130D664E45}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7129064-3DB7-4B79-81D3-80130D664E45}.Release|Any CPU.Build.0 = Release|Any CPU
{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}.Release|Any CPU.Build.0 = Release|Any CPU
{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}.Release|Any CPU.Build.0 = Release|Any CPU
{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}.Release|Any CPU.ActiveCfg = Release|Any CPU
{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}.Release|Any CPU.Build.0 = Release|Any CPU
{2C959026-7058-4302-A6C4-DFD10A030585}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C959026-7058-4302-A6C4-DFD10A030585}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C959026-7058-4302-A6C4-DFD10A030585}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C959026-7058-4302-A6C4-DFD10A030585}.Release|Any CPU.Build.0 = Release|Any CPU
{683B4041-A399-40CE-84B8-392F08A6805D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{683B4041-A399-40CE-84B8-392F08A6805D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{683B4041-A399-40CE-84B8-392F08A6805D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{683B4041-A399-40CE-84B8-392F08A6805D}.Release|Any CPU.Build.0 = Release|Any CPU
{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}.Release|Any CPU.Build.0 = Release|Any CPU
{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}.Release|Any CPU.Build.0 = Release|Any CPU
{B35E2616-DC00-48B4-BD58-7E23046257F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B35E2616-DC00-48B4-BD58-7E23046257F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B35E2616-DC00-48B4-BD58-7E23046257F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B35E2616-DC00-48B4-BD58-7E23046257F1}.Release|Any CPU.Build.0 = Release|Any CPU
{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}.Release|Any CPU.Build.0 = Release|Any CPU
{3E89ECA3-F4E7-4181-B26B-8250D5151044}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E89ECA3-F4E7-4181-B26B-8250D5151044}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E89ECA3-F4E7-4181-B26B-8250D5151044}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E89ECA3-F4E7-4181-B26B-8250D5151044}.Release|Any CPU.Build.0 = Release|Any CPU
{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}.Release|Any CPU.Build.0 = Release|Any CPU
{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}.Release|Any CPU.Build.0 = Release|Any CPU
{32D70E31-3799-482A-AC7A-081FF9206FC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32D70E31-3799-482A-AC7A-081FF9206FC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32D70E31-3799-482A-AC7A-081FF9206FC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32D70E31-3799-482A-AC7A-081FF9206FC3}.Release|Any CPU.Build.0 = Release|Any CPU
{AA72BFCE-8495-4A4D-988D-F8D490521776}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA72BFCE-8495-4A4D-988D-F8D490521776}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA72BFCE-8495-4A4D-988D-F8D490521776}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA72BFCE-8495-4A4D-988D-F8D490521776}.Release|Any CPU.Build.0 = Release|Any CPU
{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}.Release|Any CPU.Build.0 = Release|Any CPU
{D497D8BD-6EF9-4C30-B195-B0DD153418D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D497D8BD-6EF9-4C30-B195-B0DD153418D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D497D8BD-6EF9-4C30-B195-B0DD153418D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D497D8BD-6EF9-4C30-B195-B0DD153418D6}.Release|Any CPU.Build.0 = Release|Any CPU
{1765BEDB-9E4B-468C-BAF6-06784CDCED67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1765BEDB-9E4B-468C-BAF6-06784CDCED67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1765BEDB-9E4B-468C-BAF6-06784CDCED67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1765BEDB-9E4B-468C-BAF6-06784CDCED67}.Release|Any CPU.Build.0 = Release|Any CPU
{8D029A93-E687-4DDF-82B0-700EBBF477F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D029A93-E687-4DDF-82B0-700EBBF477F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D029A93-E687-4DDF-82B0-700EBBF477F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D029A93-E687-4DDF-82B0-700EBBF477F7}.Release|Any CPU.Build.0 = Release|Any CPU
{4FD7B873-1994-4990-AA40-C37060121494}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FD7B873-1994-4990-AA40-C37060121494}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FD7B873-1994-4990-AA40-C37060121494}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FD7B873-1994-4990-AA40-C37060121494}.Release|Any CPU.Build.0 = Release|Any CPU
{3E6F293D-8500-428D-BDC9-27440CC91E16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E6F293D-8500-428D-BDC9-27440CC91E16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E6F293D-8500-428D-BDC9-27440CC91E16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E6F293D-8500-428D-BDC9-27440CC91E16}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -0,0 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GIS/@EntryIndexedValue">GIS</s:String>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/@KeyIndexDefined">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=Kontakte/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=sreg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=Untappd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=xing/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=Xing/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -0,0 +1,52 @@
<GhostDoc>
<IgnoreFilePatterns>
<IgnoreFilePattern>*.min.js</IgnoreFilePattern>
<IgnoreFilePattern>jquery*.js</IgnoreFilePattern>
</IgnoreFilePatterns>
<SpellChecker>
<IncludeExtensions>
</IncludeExtensions>
<IgnoreExtensions>
</IgnoreExtensions>
<IgnoreFiles>
</IgnoreFiles>
</SpellChecker>
<HelpConfigurations selected="HelpFile">
<HelpConfiguration name="HelpFile">
<OutputPath>.\Help</OutputPath>
<CleanupOutputPath>true</CleanupOutputPath>
<HelpFileName>OwinOAuthProviders</HelpFileName>
<ImageFolderPath />
<Theme />
<HtmlFormats>
<HtmlHelp>true</HtmlHelp>
<MSHelpViewer>false</MSHelpViewer>
<MSHelp2>false</MSHelp2>
<Website>false</Website>
</HtmlFormats>
<IncludeScopes>
<Public>true</Public>
<Internal>false</Internal>
<Protected>false</Protected>
<Private>false</Private>
<Inherited>true</Inherited>
<InheritedFromReferences>true</InheritedFromReferences>
<EnableTags>false</EnableTags>
<TagList />
<AutoGeneratedDocs />
<DocsThatRequireEditing />
</IncludeScopes>
<SyntaxLanguages>
<CSharp>true</CSharp>
<VisualBasic>true</VisualBasic>
<CPlusPlus>true</CPlusPlus>
</SyntaxLanguages>
<ResolveCrefLinks>true</ResolveCrefLinks>
<HeaderText />
<FooterText />
<SelectedProjects />
</HelpConfiguration>
</HelpConfigurations>
<GeneralProperties>
</GeneralProperties>
</GhostDoc>

View File

@@ -1,5 +1,4 @@
using System.Web;
using System.Web.Optimization;
using System.Web.Optimization;
namespace OwinOAuthProvidersDemo
{

View File

@@ -1,5 +1,4 @@
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc;
namespace OwinOAuthProvidersDemo
{

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc;
using System.Web.Routing;
namespace OwinOAuthProvidersDemo

View File

@@ -1,32 +1,7 @@
using System;
using System.Security.Claims;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using Owin.Security.Providers.Asana;
using Owin.Security.Providers.ArcGISOnline;
using Owin.Security.Providers.BattleNet;
using Owin.Security.Providers.Buffer;
using Owin.Security.Providers.Dropbox;
using Owin.Security.Providers.EveOnline;
using Owin.Security.Providers.Foursquare;
using Owin.Security.Providers.GitHub;
using Owin.Security.Providers.GooglePlus;
using Owin.Security.Providers.GooglePlus.Provider;
using Owin.Security.Providers.HealthGraph;
using Owin.Security.Providers.Instagram;
using Owin.Security.Providers.LinkedIn;
using Owin.Security.Providers.Reddit;
using Owin.Security.Providers.Salesforce;
using Owin.Security.Providers.StackExchange;
using Owin.Security.Providers.TripIt;
using Owin.Security.Providers.Twitch;
using Owin.Security.Providers.Yahoo;
using Owin.Security.Providers.OpenID;
using Owin.Security.Providers.SoundCloud;
using Owin.Security.Providers.Steam;
using Owin.Security.Providers.WordPress;
namespace OwinOAuthProvidersDemo
{
@@ -43,7 +18,8 @@ namespace OwinOAuthProvidersDemo
});
// Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
//app.UseDeviantArtAuthentication("id", "secret");
//app.UseUntappdAuthentication("id", "secret");
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
@@ -64,7 +40,7 @@ namespace OwinOAuthProvidersDemo
//app.UseYahooAuthentication("", "");
//app.UseTripItAuthentication("", "");
//app.UseGitHubAuthentication("", "");
//app.UseBufferAuthentication("", "");
@@ -109,7 +85,7 @@ namespace OwinOAuthProvidersDemo
// ClientSecret = "",
// Provider = new TwitchAuthenticationProvider()
// {
// OnAuthenticated = async z =>
// {
//// Getting the twitch users picture
@@ -118,7 +94,7 @@ namespace OwinOAuthProvidersDemo
//// You should be able to access these claims with HttpContext.GetOwinContext().Authentication.GetExternalLoginInfoAsync().Claims in your Account Controller
// // Commonly used in the ExternalLoginCallback() in AccountController.cs
// /*
// if (user != null)
// {
// var claim = (await AuthenticationManager.GetExternalLoginInfoAsync()).ExternalIdentity.Claims.First(
@@ -131,7 +107,7 @@ namespace OwinOAuthProvidersDemo
// }
//};
//app.UseTwitchAuthentication(opt);
//app.UseOpenIDAuthentication("http://me.yahoo.com/", "Yahoo");
@@ -174,6 +150,8 @@ namespace OwinOAuthProvidersDemo
//};
//app.UseSalesforceAuthentication(salesforceOptions);
////app.UseShopifyAuthentication("", "");
//app.UseArcGISOnlineAuthentication(
// clientId: "",
// clientSecret: "");
@@ -190,25 +168,113 @@ namespace OwinOAuthProvidersDemo
// clientId: "",
// clientSecret: "");
//app.UseBattleNetAuthentication(new BattleNetAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = ""
//});
//app.UseBattleNetAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseBattleNetAuthentication(new BattleNetAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = ""
//});
//app.UseBattleNetAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseAsanaAuthentication("", "");
//app.UseEveOnlineAuthentication("", "");
//app.UseSoundCloudAuthentication("", "");
//app.UseSoundCloudAuthentication("", "");
//app.UseFoursquareAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseFoursquareAuthentication(
// clientId: "",
// clientSecret: "");
//app.UsePayPalAuthentication(
// clientId: "",
// clientSecret: "",
// isSandbox: false);
//app.UseWargamingAccountAuthentication("", WargamingAuthenticationOptions.Region.NorthAmerica);
//app.UseFlickrAuthentication("", "");
//app.UseVisualStudioAuthentication(
// appId: "",
// appSecret: "");
//app.UseSpotifyAuthentication(
// clientId: "",
// clientSecret: "");
//var options = new SlackAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// TeamId = "" // optional
//};
//options.Scope.Add("identify");
//app.UseSlackAuthentication(options);
//app.UseGitterAuthentication(
// clientId: "",
// clientSecret: ""
//);
//app.UseImgurAuthentication(
// new ImgurAuthenticationOptions
// {
// ClientId = "",
// ClientSecret = ""
// });
//var options = new BacklogAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// ContractName = "",
// CallbackPath = new PathString(""), // ex.new PathString("/OauthTokenRequest")
// Provider = new BacklogAuthenticationProvider
// {
// OnAuthenticated = async context => await System.Threading.Tasks.Task.Run(()=> { System.Diagnostics.Debug.WriteLine(String.Format("Refresh Token: {0}", context.RefreshToken)); })
// }
//};
//app.UseBacklogAuthentication(options);
//var cosignOptions = new CosignAuthenticationOptions
//{
// AuthenticationType = "Cosign",
// SignInAsAuthenticationType = signInAsType,
// CosignServer = "weblogin.umich.edu",
// CosignServicePort = 6663,
// IdentityServerHostInstance = "core1",
// ClientServer = "cosignservername"
//};
//app.UseCosignAuthentication(cosignOptions);
//app.UseVimeoAuthentication("", "");
//app.UseFitbitAuthentication(new FitbitAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = ""
//});
//app.UseOnshapeAuthentication(
// appKey: "",
// appSecret: "");
//
//
//app.UseOnshapeAuthentication(new OnshapeAuthenticationOptions()
//{
// AppKey = "",
// AppSecret = "",
// CallbackPath = new PathString("/oauthRedirect"),
// Hostname = "partner.dev.onshape.com"
//});
//app.UseVKontakteAuthentication("", "");
//app.UseXingAuthentication("", "");
//app.UseDoYouBuzzAuthentication("", "");
}
}
}
}

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
@@ -137,7 +133,7 @@ namespace OwinOAuthProvidersDemo.Controllers
[ValidateAntiForgeryToken]
public async Task<ActionResult> Manage(ManageUserViewModel model)
{
bool hasPassword = HasPassword();
var hasPassword = HasPassword();
ViewBag.HasLocalPassword = hasPassword;
ViewBag.ReturnUrl = Url.Action("Manage");
if (hasPassword)
@@ -182,15 +178,26 @@ namespace OwinOAuthProvidersDemo.Controllers
return View(model);
}
//////
////// POST: /Account/ExternalLogin
////[HttpPost]
////[AllowAnonymous]
////[ValidateAntiForgeryToken]
////public ActionResult ExternalLogin(string provider, string returnUrl)
////{
//// // Request a redirect to the external login provider
//// return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
////}
//
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
public ActionResult ExternalLogin(string provider, string returnUrl, string shopName = "")
{
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }), null, shopName);
}
//
@@ -224,10 +231,10 @@ namespace OwinOAuthProvidersDemo.Controllers
// POST: /Account/LinkLogin
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LinkLogin(string provider)
public ActionResult LinkLogin(string provider, string shopName)
{
// Request a redirect to the external login provider to link a login for the current user
return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId(), shopName);
}
//
@@ -324,6 +331,8 @@ namespace OwinOAuthProvidersDemo.Controllers
#region Helpers
// Used for XSRF protection when adding external logins
private const string XsrfKey = "XsrfId";
// Used for Shopify external login to provide shopname while building endpoints.
private const string ShopNameKey = "ShopName";
private IAuthenticationManager AuthenticationManager
{
@@ -380,20 +389,22 @@ namespace OwinOAuthProvidersDemo.Controllers
private class ChallengeResult : HttpUnauthorizedResult
{
public ChallengeResult(string provider, string redirectUri) : this(provider, redirectUri, null)
public ChallengeResult(string provider, string redirectUri) : this(provider, redirectUri, null, null)
{
}
public ChallengeResult(string provider, string redirectUri, string userId)
public ChallengeResult(string provider, string redirectUri, string userId, string shopName)
{
LoginProvider = provider;
RedirectUri = redirectUri;
UserId = userId;
ShopName = shopName;
}
public string LoginProvider { get; set; }
public string RedirectUri { get; set; }
public string UserId { get; set; }
public string ShopName { get; set; }
public override void ExecuteResult(ControllerContext context)
{
@@ -402,6 +413,12 @@ namespace OwinOAuthProvidersDemo.Controllers
{
properties.Dictionary[XsrfKey] = UserId;
}
if (!string.IsNullOrWhiteSpace(ShopName))
{
properties.Dictionary[ShopNameKey] = ShopName;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc;
namespace OwinOAuthProvidersDemo.Controllers
{

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

View File

@@ -20,6 +20,7 @@
<IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>
<IISExpressWindowsAuthentication>disabled</IISExpressWindowsAuthentication>
<IISExpressUseClassicPipelineMode>false</IISExpressUseClassicPipelineMode>
<UseGlobalApplicationHostFile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -40,69 +41,77 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Antlr3.Runtime, Version=3.5.0.2, Culture=neutral, PublicKeyToken=eb42632606e9261f, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.1.0\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.EntityFramework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Identity.EntityFramework.2.1.0\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Owin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Identity.Owin.2.1.0\lib\net45\Microsoft.AspNet.Identity.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.2.1.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.Cookies, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.Facebook, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.Facebook.2.1.0\lib\net45\Microsoft.Owin.Security.Facebook.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.Google, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.Google.2.1.0\lib\net45\Microsoft.Owin.Security.Google.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.MicrosoftAccount, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.MicrosoftAccount.2.1.0\lib\net45\Microsoft.Owin.Security.MicrosoftAccount.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.OAuth, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.OAuth.2.1.0\lib\net45\Microsoft.Owin.Security.OAuth.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.Twitter, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.Twitter.2.1.0\lib\net45\Microsoft.Owin.Security.Twitter.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -114,32 +123,32 @@
<Reference Include="System.Core" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.Helpers.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.0\lib\net45\System.Web.Mvc.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Optimization, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Razor.3.2.0\lib\net45\System.Web.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Web" />
@@ -150,22 +159,13 @@
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http">
</Reference>
<Reference Include="System.Net.Http.WebRequest">
</Reference>
<Reference Include="WebGrease, Version=1.6.5135.21930, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\WebGrease.1.6.0\lib\WebGrease.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -195,14 +195,13 @@
<Content Include="fonts\glyphicons-halflings-regular.woff" />
<Content Include="fonts\glyphicons-halflings-regular.ttf" />
<Content Include="fonts\glyphicons-halflings-regular.eot" />
<Content Include="Content\bootstrap-theme.css.map" />
<Content Include="Content\bootstrap.css.map" />
<Content Include="Content\bootstrap-theme.css.map" />
<None Include="Scripts\jquery-2.1.1.intellisense.js" />
<Content Include="Scripts\bootstrap.js" />
<Content Include="Scripts\bootstrap.min.js" />
<Content Include="Scripts\jquery-2.1.1.js" />
<Content Include="Scripts\jquery-2.1.1.min.js" />
<Content Include="Scripts\jquery-2.1.1.min.map" />
<None Include="Scripts\jquery.validate-vsdoc.js" />
<Content Include="Scripts\jquery.validate.js" />
<Content Include="Scripts\jquery.validate.min.js" />
@@ -245,13 +244,9 @@
</ItemGroup>
<ItemGroup>
<Content Include="packages.config" />
<None Include="Project_Readme.html" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Owin.Security.Providers\Owin.Security.Providers.csproj">
<Project>{6ad9ba00-1330-426d-8bae-2d3bc0d976e4}</Project>
<Name>Owin.Security.Providers</Name>
</ProjectReference>
<Content Include="Scripts\jquery-2.1.1.min.map" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>

View File

@@ -1,151 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Your ASP.NET application</title>
<style>
body {
background: #fff;
color: #505050;
font: 14px 'Segoe UI', tahoma, arial, helvetica, sans-serif;
margin: 20px;
padding: 0;
}
#header {
background: #efefef;
padding: 0;
}
h1 {
font-size: 48px;
font-weight: normal;
margin: 0;
padding: 0 30px;
line-height: 150px;
}
p {
font-size: 20px;
color: #fff;
background: #969696;
padding: 0 30px;
line-height: 50px;
}
#main {
padding: 5px 30px;
}
.section {
width: 21.7%;
float: left;
margin: 0 0 0 4%;
}
.section h2 {
font-size: 13px;
text-transform: uppercase;
margin: 0;
border-bottom: 1px solid silver;
padding-bottom: 12px;
margin-bottom: 8px;
}
.section.first {
margin-left: 0;
}
.section.first h2 {
font-size: 24px;
text-transform: none;
margin-bottom: 25px;
border: none;
}
.section.first li {
border-top: 1px solid silver;
padding: 8px 0;
}
.section.last {
margin-right: 0;
}
ul {
list-style: none;
padding: 0;
margin: 0;
line-height: 20px;
}
li {
padding: 4px 0;
}
a {
color: #267cb2;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div id="header">
<h1>Your ASP.NET application</h1>
<p>Congratulations! You've created a project</p>
</div>
<div id="main">
<div class="section first">
<h2>This application consists of:</h2>
<ul>
<li>Sample pages showing basic nav between Home, About, and Contact</li>
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=320754">Bootstrap</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320755">Authentication</a>, if selected, shows how to register and sign in</li>
<li>ASP.NET features managed using <a href="http://go.microsoft.com/fwlink/?LinkID=320756">NuGet</a></li>
</ul>
</div>
<div class="section">
<h2>Customize app</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320757">Get started with ASP.NET MVC</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320758">Change the site's theme</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320759">Add more libraries using NuGet</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320760">Configure authentication</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320761">Customize information about the website users</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320762">Get information from social providers</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320763">Add HTTP services using ASP.NET Web API</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320764">Secure your web API</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320765">Add real-time web with ASP.NET SignalR</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320766">Add components using Scaffolding</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320767">Test your app with Browser Link</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320768">Share your project</a></li>
</ul>
</div>
<div class="section">
<h2>Deploy</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320769">Ensure your app is ready for production</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320770">Windows Azure</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320771">Hosting providers</a></li>
</ul>
</div>
<div class="section last">
<h2>Get help</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320772">Get help</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320773">Get more templates</a></li>
</ul>
</div>
</div>
</body>
</html>

View File

@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following

View File

@@ -1,9 +1,10 @@
/// <autosync enabled="true" />
/// <reference path="bootstrap.js" />
/// <reference path="bootstrap.min.js" />
/// <reference path="jquery.validate.min.js" />
/// <reference path="jquery.validate.unobtrusive.min.js" />
/// <reference path="jquery-2.1.1.js" />
/// <reference path="jquery.validate.js" />
/// <reference path="jquery.validate.unobtrusive.js" />
/// <reference path="jquery-2.1.1.min.js" />
/// <reference path="modernizr-2.6.2.js" />
/// <reference path="modernizr-2.7.2.js" />
/// <reference path="respond.js" />
/// <reference path="respond.matchmedia.addlistener.js" />
/// <reference path="respond.matchmedia.addlistener.min.js" />
/// <reference path="respond.min.js" />

View File

@@ -49,7 +49,7 @@ window.Modernizr = (function( window, document, undefined ) {
var version = '2.6.2',
Modernizr = {},
modernizr = {},
/*>>cssclasses*/
// option for enabling the HTML classes to be added
@@ -207,7 +207,7 @@ window.Modernizr = (function( window, document, undefined ) {
// ...
isEventSupported = (function() {
var TAGNAMES = {
var tagnames = {
'select': 'input', 'change': 'input',
'submit': 'form', 'reset': 'form',
'error': 'img', 'load': 'img', 'abort': 'img'
@@ -215,7 +215,7 @@ window.Modernizr = (function( window, document, undefined ) {
function isEventSupported( eventName, element ) {
element = element || document.createElement(TAGNAMES[eventName] || 'div');
element = element || document.createElement(tagnames[eventName] || 'div');
eventName = 'on' + eventName;
// When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
@@ -248,11 +248,11 @@ window.Modernizr = (function( window, document, undefined ) {
// TODO :: Add flag for hasownprop ? didn't last time
// hasOwnProperty shim by kangax needed for Safari 2.0 support
_hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
if ( !is(hasOwnProperty, 'undefined') && !is(hasOwnProperty.call, 'undefined') ) {
hasOwnProp = function (object, property) {
return _hasOwnProperty.call(object, property);
return hasOwnProperty.call(object, property);
};
}
else {
@@ -278,9 +278,9 @@ window.Modernizr = (function( window, document, undefined ) {
if (this instanceof bound) {
var F = function(){};
F.prototype = target.prototype;
var self = new F();
var f = function(){};
f.prototype = target.prototype;
var self = new f();
var result = target.apply(
self,
@@ -370,7 +370,7 @@ window.Modernizr = (function( window, document, undefined ) {
* testDOMProps is a generic DOM property test; if a browser supports
* a certain property, it won't return undefined for it.
*/
function testDOMProps( props, obj, elem ) {
function testDomProps( props, obj, elem ) {
for ( var i in props ) {
var item = obj[props[i]];
if ( item !== undefined) {
@@ -410,7 +410,7 @@ window.Modernizr = (function( window, document, undefined ) {
// otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
} else {
props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
return testDOMProps(props, prefixed, elem);
return testDomProps(props, prefixed, elem);
}
}
/*>>testallprops*/
@@ -445,7 +445,7 @@ window.Modernizr = (function( window, document, undefined ) {
};
tests['canvastext'] = function() {
return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
return !!(modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
};
// webk.it/70117 is tracking a legit WebGL feature detect proposal
@@ -881,7 +881,7 @@ window.Modernizr = (function( window, document, undefined ) {
// Only input placeholder is tested while textarea's placeholder is not.
// Currently Safari 4 and Opera 11 have support only for the input placeholder
// Both tests are available in feature-detects/forms-placeholder.js
Modernizr['input'] = (function( props ) {
modernizr['input'] = (function( props ) {
for ( var i = 0, len = props.length; i < len; i++ ) {
attrs[ props[i] ] = !!(props[i] in inputElem);
}
@@ -901,7 +901,7 @@ window.Modernizr = (function( window, document, undefined ) {
// containing each input type with its corresponding true/false value
// Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
Modernizr['inputtypes'] = (function(props) {
modernizr['inputtypes'] = (function(props) {
for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
@@ -969,15 +969,15 @@ window.Modernizr = (function( window, document, undefined ) {
// then based on that boolean, define an appropriate className
// and push it into an array of classes we'll join later.
featureName = feature.toLowerCase();
Modernizr[featureName] = tests[feature]();
modernizr[featureName] = tests[feature]();
classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
classes.push((modernizr[featureName] ? '' : 'no-') + featureName);
}
}
/*>>webforms*/
// input tests need to run.
Modernizr.input || webforms();
modernizr.input || webforms();
/*>>webforms*/
@@ -989,24 +989,24 @@ window.Modernizr = (function( window, document, undefined ) {
* @param feature - String naming the feature
* @param test - Function returning true if feature is supported, false if not
*/
Modernizr.addTest = function ( feature, test ) {
modernizr.addTest = function ( feature, test ) {
if ( typeof feature == 'object' ) {
for ( var key in feature ) {
if ( hasOwnProp( feature, key ) ) {
Modernizr.addTest( key, feature[ key ] );
modernizr.addTest( key, feature[ key ] );
}
}
} else {
feature = feature.toLowerCase();
if ( Modernizr[feature] !== undefined ) {
if ( modernizr[feature] !== undefined ) {
// we're going to quit if you're trying to overwrite an existing test
// if we were to allow it, we'd do this:
// var re = new RegExp("\\b(no-)?" + feature + "\\b");
// docElement.className = docElement.className.replace( re, '' );
// but, no rly, stuff 'em.
return Modernizr;
return modernizr;
}
test = typeof test == 'function' ? test() : test;
@@ -1014,11 +1014,11 @@ window.Modernizr = (function( window, document, undefined ) {
if (typeof enableClasses !== "undefined" && enableClasses) {
docElement.className += ' ' + (test ? '' : 'no-') + feature;
}
Modernizr[feature] = test;
modernizr[feature] = test;
}
return Modernizr; // allow chaining.
return modernizr; // allow chaining.
};
@@ -1046,7 +1046,7 @@ window.Modernizr = (function( window, document, undefined ) {
var expando = '_html5shiv';
/** The id for the the documents expando */
var expanID = 0;
var expanId = 0;
/** Cached data for each document */
var expandoData = {};
@@ -1115,9 +1115,9 @@ window.Modernizr = (function( window, document, undefined ) {
var data = expandoData[ownerDocument[expando]];
if (!data) {
data = {};
expanID++;
ownerDocument[expando] = expanID;
expandoData[expanID] = data;
expanId++;
ownerDocument[expando] = expanId;
expandoData[expanId] = data;
}
return data;
}
@@ -1318,15 +1318,15 @@ window.Modernizr = (function( window, document, undefined ) {
/*>>shiv*/
// Assign private properties to the return object with prefix
Modernizr._version = version;
modernizr._version = version;
// expose these for the plugin API. Look in the source for how to join() them against your input
/*>>prefixes*/
Modernizr._prefixes = prefixes;
modernizr._prefixes = prefixes;
/*>>prefixes*/
/*>>domprefixes*/
Modernizr._domPrefixes = domPrefixes;
Modernizr._cssomPrefixes = cssomPrefixes;
modernizr._domPrefixes = domPrefixes;
modernizr._cssomPrefixes = cssomPrefixes;
/*>>domprefixes*/
/*>>mq*/
@@ -1338,20 +1338,20 @@ window.Modernizr = (function( window, document, undefined ) {
// Modernizr.mq('(min-width:0)')
// usage:
// Modernizr.mq('only screen and (max-width:768)')
Modernizr.mq = testMediaQuery;
modernizr.mq = testMediaQuery;
/*>>mq*/
/*>>hasevent*/
// Modernizr.hasEvent() detects support for a given event, with an optional element to test on
// Modernizr.hasEvent('gesturestart', elem)
Modernizr.hasEvent = isEventSupported;
modernizr.hasEvent = isEventSupported;
/*>>hasevent*/
/*>>testprop*/
// Modernizr.testProp() investigates whether a given style property is recognized
// Note that the property names must be provided in the camelCase variant.
// Modernizr.testProp('pointerEvents')
Modernizr.testProp = function(prop){
modernizr.testProp = function(prop){
return testProps([prop]);
};
/*>>testprop*/
@@ -1361,14 +1361,14 @@ window.Modernizr = (function( window, document, undefined ) {
// or any of its vendor-prefixed variants, is recognized
// Note that the property names must be provided in the camelCase variant.
// Modernizr.testAllProps('boxSizing')
Modernizr.testAllProps = testPropsAll;
modernizr.testAllProps = testPropsAll;
/*>>testallprops*/
/*>>teststyles*/
// Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
// Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
Modernizr.testStyles = injectElementWithStyles;
modernizr.testStyles = injectElementWithStyles;
/*>>teststyles*/
@@ -1392,7 +1392,7 @@ window.Modernizr = (function( window, document, undefined ) {
// },
// transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
Modernizr.prefixed = function(prop, obj, elem){
modernizr.prefixed = function(prop, obj, elem){
if(!obj) {
return testPropsAll(prop, 'pfx');
} else {
@@ -1411,6 +1411,6 @@ window.Modernizr = (function( window, document, undefined ) {
(enableClasses ? ' js ' + classes.join(' ') : '');
/*>>cssclasses*/
return Modernizr;
return modernizr;
})(this, this.document);

View File

@@ -1,6 +1,4 @@
@using OwinOAuthProvidersDemo.Models;
@using Microsoft.AspNet.Identity;
@{
@{
ViewBag.Title = "Manage Account";
}

View File

@@ -24,6 +24,10 @@
<p>
@foreach (AuthenticationDescription p in loginProviders)
{
if (p.AuthenticationType.Equals("Shopify"))
{
@Html.TextBox("shopName")
}
<button type="submit" class="btn btn-default" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="Log in using your @p.Caption account">@p.AuthenticationType</button>
}
</p>

View File

@@ -5,11 +5,12 @@
-->
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-OwinOAuthProvidersDemo-20131113093838.mdf;Initial Catalog=aspnet-OwinOAuthProvidersDemo-20131113093838;Integrated Security=True" providerName="System.Data.SqlClient" />
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-OwinOAuthProvidersDemo-2015.mdf;Initial Catalog=aspnet-OwinOAuthProvidersDemo-20131113093838;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />

View File

@@ -5,28 +5,64 @@
Provides a set of extra authentication providers for OWIN ([Project Katana](http://katanaproject.codeplex.com/)). This project includes providers for:
- OAuth
- Google+
- Yahoo
- LinkedIn
- GitHub
- Instagram
- StackExchange
- HealthGraph
- Battle.net
- ArcGISOnline
- Asana
- Backlog
- Battle.net
- Bitbucket
- Buffer
- Cosign
- DeviantArt
- Dropbox
- EVEOnline
- Fitbit
- Flickr
- Foursquare
- GitHub
- Gitter
- Google+
- HealthGraph
- Instagram
- LinkedIn
- Onshape
- PayPal
- Reddit
- Salesforce
- Shopify
- Slack
- SoundCloud
- Spotify
- StackExchange
- TripIt
- Twitch.tv
- Untappd
- Vimeo
- Visual Studio Online
- VKontakte
- Wordpress
- Xing
- Yahoo
- Yammer
- OpenID
- Generic OpenID 2.0 provider
- Steam
- Wargaming
## Implementation Guides
For guides on how to implement these providers, please visit my blog, [Be a Big Rockstar](http://www.beabigrockstar.com).
For above listed provider implementation guide, visit Jerrie Pelser's blog - [Be a Big Rockstar](http://www.beabigrockstar.com)
## Installation
To use these providers you will need to install the ```Owin.Security.Providers``` NuGet package.
```
PM> Install-Package Owin.Security.Providers
PM> Install-Package Owin.Security.Providers.*
```
Where * is the name of the provider you need e.g.:
```
PM> Install-Package Owin.Security.Providers.GitHub
```
I haven't published all of the providers yet as of 4/12/2016.
## Contributions
@@ -47,12 +83,20 @@ A big thanks goes out to all these contributors without whom this would not have
* Aaron Horst (https://github.com/aaron-horst)
* Scott Hill (https://github.com/scottedwardhill)
* Anthony Ruffino (https://github.com/AnthonyRuffino)
* Tommy Parnell (https://github.com/tparnell8)
* Maxime Roussin-Bélanger (https://github.com/Lorac)
* Jaspalsinh Chauhan (https://github.com/jsinh)
* Jason Loeffler (https://github.com/jmloeffler)
* Ben Foster (https://github.com/benfoster)
* Jonathan Peterson (https://github.com/eonasdan)
For most accurate and up to date list of contributors please see https://github.com/RockstarLabs/OwinOAuthProviders/graphs/contributors
## License
The MIT License (MIT)
Copyright (c) 2014 Jerrie Pelser
Copyright (c) 2014, 2015 Jerrie Pelser
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

72
Rakefile.rb Normal file
View File

@@ -0,0 +1,72 @@
require 'rake'
require 'erb'
require 'rake/clean'
require 'albacore'
require 'open-uri'
require 'fileutils'
require 'os'
require 'nokogiri'
require 'openssl'
import 'nuget.rake'
CLEAN.include(['src/**/obj', 'src/**/bin', 'tool', 'packages/**','src/**/*.nuspec', 'src/**/*.nupkg', 'tools', 'packages', '*.nupkg'])
Configuration = ENV['CONFIGURATION'] || 'Release'
PACKAGES = File.expand_path("packages")
TOOLS = File.expand_path("tools")
NUGET = File.expand_path("#{TOOLS}/nuget")
NUGET_EXE = File.expand_path("#{TOOLS}/nuget/nuget.exe")
@version = "2.0.0-rc1"
PROJECTS = Dir.glob('src/*').select{|dir| File.directory? dir }
desc 'Retrieve things'
task :retrieve => ["nuget:fetch"]
desc 'Does the build'
task :build => [:retrieve, :compile]
desc 'clean, retrieve, build, generate nuspecs'
task :preflight => [:clean, :build, :nuspec_gen]
desc 'publish'
task :publish => [:preflight,:nuspec_gen, :nuspec_pack, :nuspec_publish]
build :compile do |t|
t.prop 'Configuration', Configuration
t.sln = 'OwinOAuthProviders.sln'
end
desc "Generate nuspec files"
task :nuspec_gen do
template = ERB.new(File.read('nuspectemplate.nuspec.erb'))
@nugets = []
PROJECTS.each{|directory|
@id = File.basename(directory)
@nugets.push(@id)
output = template.result()
File.write(File.join(directory, "#{@id}.nuspec"), output)
}
File.write('Owin.Security.Providers.nuspec', ERB.new(File.read('global.nuspec.erb')).result())
end
desc 'pack nuspec files'
task :nuspec_pack do
PROJECTS.each{|dir|
Dir.chdir(dir) do
sh "#{NUGET_EXE} pack #{FileList["*.csproj"].first} -Prop Configuration=#{Configuration}"
end
}
sh "#{NUGET_EXE} pack Owin.Security.Providers.nuspec -Exclude \"**\""
end
desc 'publish nugets'
task :nuspec_publish do
PROJECTS.each{|dir|
Dir.chdir(dir) do
sh "#{NUGET_EXE} push #{FileList["*.nupkg"].first}"
end
}
sh "#{NUGET_EXE} push #{FileList["*.nupkg"].first}"
end

View File

@@ -1,5 +1,10 @@
version: 1.0.{build}
before_build:
- ps: nuget restore
build:
verbosity: minimal
nuget:
project_feed: true
build_script:
- ps: >-
gem install bundle
bundle
rake preflight
artifacts:
- path: src\**\*.nupkg

View File

@@ -0,0 +1,8 @@

namespace Owin.Security.Providers.OpenIDBase
{
public static class Constants
{
public const string DefaultAuthenticationType = "OpenID";
}
}

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Owin.Security.Providers.OpenID.Extensions
namespace Owin.Security.Providers.OpenIDBase.Extensions
{
/// <summary>
/// Contains an extension method that makes reading the SREG fields easier.

View File

@@ -4,15 +4,14 @@ using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Owin.Security.Providers.OpenID.Extensions
namespace Owin.Security.Providers.OpenIDBase.Extensions
{
/// <summary>
/// Implements the OpenID Simple Registration Extension http://openid.net/specs/openid-simple-registration-extension-1_0.html
/// </summary>
public class OpenIDSimpleRegistrationExtension : IOpenIDProtocolExtension
{
private static readonly Dictionary<OpenIDSimpleRegistrationField, string> claimsMap = new Dictionary<OpenIDSimpleRegistrationField, string>()
private static readonly Dictionary<OpenIDSimpleRegistrationField, string> ClaimsMap = new Dictionary<OpenIDSimpleRegistrationField, string>()
{
{ OpenIDSimpleRegistrationField.NickName, "nickname" },
{ OpenIDSimpleRegistrationField.FullName, "fullname" },
@@ -25,18 +24,18 @@ namespace Owin.Security.Providers.OpenID.Extensions
{ OpenIDSimpleRegistrationField.Timezone, "timezone" }
};
private const string sregNamespace = "http://openid.net/extensions/sreg/1.1";
private const string SimpleRegistrationNamespace = "http://openid.net/extensions/sreg/1.1";
/// <summary>
/// Gets or sets a list of comma-separated SREG fields that are required.
/// </summary>
public HashSet<OpenIDSimpleRegistrationField> RequiredFields { get; private set; }
public HashSet<OpenIDSimpleRegistrationField> RequiredFields { get; }
/// <summary>
/// Gets or sets a list of comma-separated SREG fields that are optional.
/// </summary>
public HashSet<OpenIDSimpleRegistrationField> OptionalFields { get; private set; }
public HashSet<OpenIDSimpleRegistrationField> OptionalFields { get; }
/// <summary>
/// Gets or sets the SREG policy URL.
@@ -60,14 +59,14 @@ namespace Owin.Security.Providers.OpenID.Extensions
/// </summary>
public Task OnChallengeAsync(Microsoft.Owin.Security.AuthenticationResponseChallenge challenge, OpenIDAuthorizationEndpointInfo endpoint)
{
endpoint.Url += "&openid.ns.sreg=" + Uri.EscapeDataString(sregNamespace);
endpoint.Url += "&openid.ns.sreg=" + Uri.EscapeDataString(SimpleRegistrationNamespace);
var requiredClaims = string.Join(",", RequiredFields.Select(f => claimsMap[f]));
var requiredClaims = string.Join(",", RequiredFields.Select(f => ClaimsMap[f]));
endpoint.Url += "&openid.sreg.required=" + Uri.EscapeDataString(requiredClaims);
if (OptionalFields.Any())
{
var optionalClaims = string.Join(",", OptionalFields.Select(f => claimsMap[f]));
var optionalClaims = string.Join(",", OptionalFields.Select(f => ClaimsMap[f]));
endpoint.Url += "&openid.sreg.optional=" + Uri.EscapeDataString(optionalClaims);
}
@@ -94,10 +93,10 @@ namespace Owin.Security.Providers.OpenID.Extensions
public Task<object> OnExtractResultsAsync(ClaimsIdentity identity, string claimedId, Infrastructure.Message message)
{
var result = new OpenIDSimpleRegistrationResult();
foreach (var claim in claimsMap)
foreach (var claim in ClaimsMap)
{
string value;
if (message.TryGetValue(claim.Value + "." + sregNamespace, out value))
if (message.TryGetValue(claim.Value + "." + SimpleRegistrationNamespace, out value))
{
result.Values.Add(claim.Key, value);
}

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Owin.Security.Providers.OpenID.Extensions
namespace Owin.Security.Providers.OpenIDBase.Extensions
{
public enum OpenIDSimpleRegistrationField
{

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
namespace Owin.Security.Providers.OpenID.Extensions
namespace Owin.Security.Providers.OpenIDBase.Extensions
{
/// <summary>
/// Contains values of OpenID Simple Registration Extension fields.

View File

@@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Microsoft.Owin.Security;
namespace Owin.Security.Providers.OpenID
namespace Owin.Security.Providers.OpenIDBase
{
public interface IOpenIDProtocolExtension
{

View File

@@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Owin.Security.Providers.OpenID.Infrastructure
namespace Owin.Security.Providers.OpenIDBase.Infrastructure
{
public class Message
{
@@ -14,8 +14,8 @@ namespace Owin.Security.Providers.OpenID.Infrastructure
Add(parameters, strict);
}
public Dictionary<string, Property> Namespaces { get; private set; }
public Dictionary<string, Property> Properties { get; private set; }
public Dictionary<string, Property> Namespaces { get; }
public Dictionary<string, Property> Properties { get; }
/// <summary>
/// Adds the openid parameters from querystring or form body into Namespaces and Properties collections.
@@ -32,7 +32,7 @@ namespace Owin.Security.Providers.OpenID.Infrastructure
// strict is true if keys that are not signed should be strict
if (strict)
{
IList<string> signed = parameters.GetValues("openid.signed");
var signed = parameters.GetValues("openid.signed");
if (signed == null ||
signed.Count != 1)
{
@@ -60,7 +60,7 @@ namespace Owin.Security.Providers.OpenID.Infrastructure
// Key is the raw key name. The Name starts of being equal to Key with a
// trailing dot appended. The Value is the query or form value, with a comma delimiter
// inserted between multiply occuring values.
Property[] addingProperties = addingParameters.Select(kv => new Property
var addingProperties = addingParameters.Select(kv => new Property
{
Key = kv.Key,
Name = kv.Key + ".",
@@ -70,21 +70,17 @@ namespace Owin.Security.Providers.OpenID.Infrastructure
// first, recognize which parameters are namespace declarations
var namespacePrefixes = new Dictionary<string, Property>(StringComparer.Ordinal);
foreach (var item in addingProperties)
foreach (var item in addingProperties.Where(item => item.Name.StartsWith("openid.ns.", StringComparison.Ordinal)))
{
// namespaces appear as with "openid.ns" or "openid.ns.alias"
if (item.Name.StartsWith("openid.ns.", StringComparison.Ordinal))
{
// the value of the parameter is the uri of the namespace
item.Namespace = item.Value;
item.Name = "openid." + item.Name.Substring("openid.ns.".Length);
// the value of the parameter is the uri of the namespace
item.Namespace = item.Value;
item.Name = "openid." + item.Name.Substring("openid.ns.".Length);
// the namespaces collection is keyed by the ns uri
Namespaces.Add(item.Namespace, item);
// the namespaces collection is keyed by the ns uri
Namespaces.Add(item.Namespace, item);
// and the prefixes collection is keyed by "openid.alias."
namespacePrefixes.Add(item.Name, item);
}
// and the prefixes collection is keyed by "openid.alias."
namespacePrefixes.Add(item.Name, item);
}
// second, recognize which parameters are property values
@@ -92,41 +88,39 @@ namespace Owin.Security.Providers.OpenID.Infrastructure
foreach (var item in addingProperties)
{
// anything with a namespace was already added to Namespaces
if (item.Namespace == null)
if (item.Namespace != null) continue;
// look for the namespace match for this property.
Property match = null;
// try finding where openid.alias.arg2 matches openid.ns.alies namespace
if (item.Name.StartsWith("openid.", StringComparison.Ordinal))
{
// look for the namespace match for this property.
Property match = null;
// try finding where openid.alias.arg2 matches openid.ns.alies namespace
if (item.Name.StartsWith("openid.", StringComparison.Ordinal))
var dotIndex = item.Name.IndexOf('.', "openid.".Length);
if (dotIndex != -1)
{
int dotIndex = item.Name.IndexOf('.', "openid.".Length);
if (dotIndex != -1)
{
string namespacePrefix = item.Name.Substring(0, dotIndex + 1);
namespacePrefixes.TryGetValue(namespacePrefix, out match);
}
var namespacePrefix = item.Name.Substring(0, dotIndex + 1);
namespacePrefixes.TryGetValue(namespacePrefix, out match);
}
// then try finding where openid.arg1 should match openid.ns namespace
if (match == null)
{
namespacePrefixes.TryGetValue("openid.", out match);
}
// when a namespace is found
if (match != null)
{
// the property's namespace is defined, and the namespace's prefix is removed
item.Namespace = match.Namespace;
item.Name = item.Name.Substring(match.Name.Length);
}
// the resulting property key is keyed by the local name and namespace
// so "openid.arg1" becomes "arg1.namespace-uri-of-openid"
// and "openid.alias.arg2" becomes "arg2.namespace-uri-of-alias"
Properties.Add(item.Name + item.Namespace, item);
}
// then try finding where openid.arg1 should match openid.ns namespace
if (match == null)
{
namespacePrefixes.TryGetValue("openid.", out match);
}
// when a namespace is found
if (match != null)
{
// the property's namespace is defined, and the namespace's prefix is removed
item.Namespace = match.Namespace;
item.Name = item.Name.Substring(match.Name.Length);
}
// the resulting property key is keyed by the local name and namespace
// so "openid.arg1" becomes "arg1.namespace-uri-of-openid"
// and "openid.alias.arg2" becomes "arg2.namespace-uri-of-alias"
Properties.Add(item.Name + item.Namespace, item);
}
}

View File

@@ -1,5 +1,5 @@

namespace Owin.Security.Providers.OpenID.Infrastructure
namespace Owin.Security.Providers.OpenIDBase.Infrastructure
{
public class Property
{

View File

@@ -1,9 +1,3 @@
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.OpenID.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -15,32 +9,31 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.OpenIDBase.Infrastructure;
namespace Owin.Security.Providers.OpenID
namespace Owin.Security.Providers.OpenIDBase
{
internal class OpenIDAuthenticationHandler : OpenIDAuthenticationHandlerBase<OpenIDAuthenticationOptions>
public abstract class OpenIDAuthenticationHandlerBase<T> : AuthenticationHandler<T> where T : OpenIDAuthenticationOptions
{
public OpenIDAuthenticationHandler(HttpClient httpClient, ILogger logger)
: base(httpClient, logger)
{ }
}
private const string ContenttypeXrds = "application/xrds+xml";
private const string ContenttypeHTML = "text/html";
private const string ContenttypeXhtml = "application/xhtml+xml";
private const string ContenttypeXml = "text/xml";
private const string XrdsLocationheader = "X-XRDS-Location";
private const string XrdNamespace = "xri://$xrd*($v*2.0)";
internal abstract class OpenIDAuthenticationHandlerBase<T> : AuthenticationHandler<T> where T : OpenIDAuthenticationOptions
{
private const string CONTENTTYPE_XRDS = "application/xrds+xml";
private const string CONTENTTYPE_HTML = "text/html";
private const string CONTENTTYPE_XHTML = "application/xhtml+xml";
private const string CONTENTTYPE_XML = "text/xml";
private const string XRDS_LOCATIONHEADER = "X-XRDS-Location";
private const string XRD_NAMESPACE = "xri://$xrd*($v*2.0)";
protected readonly ILogger Logger;
protected readonly HttpClient HTTPClient;
protected readonly ILogger _logger;
protected readonly HttpClient _httpClient;
public OpenIDAuthenticationHandlerBase(HttpClient httpClient, ILogger logger)
protected OpenIDAuthenticationHandlerBase(HttpClient httpClient, ILogger logger)
{
_httpClient = httpClient;
_logger = logger;
HTTPClient = httpClient;
Logger = logger;
}
public override async Task<bool> InvokeAsync()
@@ -58,35 +51,35 @@ namespace Owin.Security.Providers.OpenID
try
{
IReadableStringCollection query = Request.Query;
var query = Request.Query;
properties = UnpackStateParameter(query);
if (properties == null)
{
_logger.WriteWarning("Invalid return state");
Logger.WriteWarning("Invalid return state");
return null;
}
// Anti-CSRF
if (!ValidateCorrelationId(properties, _logger))
if (!ValidateCorrelationId(properties, Logger))
{
return new AuthenticationTicket(null, properties);
}
Message message = await ParseRequestMessageAsync(query);
var message = await ParseRequestMessageAsync(query);
bool messageValidated = false;
var messageValidated = false;
Property mode;
if (!message.Properties.TryGetValue("mode.http://specs.openid.net/auth/2.0", out mode))
{
_logger.WriteWarning("Missing mode parameter");
Logger.WriteWarning("Missing mode parameter");
return new AuthenticationTicket(null, properties);
}
if (string.Equals("cancel", mode.Value, StringComparison.Ordinal))
{
_logger.WriteWarning("User cancelled signin request");
Logger.WriteWarning("User cancelled signin request");
return new AuthenticationTicket(null, properties);
}
@@ -96,31 +89,24 @@ namespace Owin.Security.Providers.OpenID
var requestBody = new FormUrlEncodedContent(message.ToFormValues());
HttpResponseMessage response = await _httpClient.PostAsync(Options.ProviderLoginUri, requestBody, Request.CallCancelled);
var response = await HTTPClient.PostAsync(Options.ProviderLoginUri, requestBody, Request.CallCancelled);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
var responseBody = await response.Content.ReadAsStringAsync();
var verifyBody = new Dictionary<string, string[]>();
foreach (var line in responseBody.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
{
int delimiter = line.IndexOf(':');
var delimiter = line.IndexOf(':');
if (delimiter != -1)
{
verifyBody.Add("openid." + line.Substring(0, delimiter), new[] { line.Substring(delimiter + 1) });
}
}
var verifyMessage = new Message(new ReadableStringCollection(verifyBody), strict: false);
var verifyMessage = new Message(new ReadableStringCollection(verifyBody), false);
Property isValid;
if (verifyMessage.Properties.TryGetValue("is_valid.http://specs.openid.net/auth/2.0", out isValid))
{
if (string.Equals("true", isValid.Value, StringComparison.Ordinal))
{
messageValidated = true;
}
else
{
messageValidated = false;
}
messageValidated = string.Equals("true", isValid.Value, StringComparison.Ordinal);
}
}
@@ -135,7 +121,7 @@ namespace Owin.Security.Providers.OpenID
string actualReturnTo;
if (!message.TryGetValue("return_to.http://specs.openid.net/auth/2.0", out actualReturnTo))
{
_logger.WriteWarning("openid.return_to parameter missing at return address");
Logger.WriteWarning("openid.return_to parameter missing at return address");
messageValidated = false;
}
else
@@ -143,11 +129,11 @@ namespace Owin.Security.Providers.OpenID
// create the expected return_to parameter based on the URL that is processing
// the assertion, plus exactly and only the the query string parameter (state)
// that this RP must have received
string expectedReturnTo = BuildReturnTo(GetStateParameter(query));
var expectedReturnTo = BuildReturnTo(GetStateParameter(query));
if (!string.Equals(actualReturnTo, expectedReturnTo, StringComparison.Ordinal))
{
_logger.WriteWarning("openid.return_to parameter not equal to expected value based on return address");
Logger.WriteWarning("openid.return_to parameter not equal to expected value based on return address");
messageValidated = false;
}
}
@@ -162,20 +148,17 @@ namespace Owin.Security.Providers.OpenID
}
}
if (messageValidated)
if (!messageValidated) return new AuthenticationTicket(null, properties);
{
IDictionary<string, string> attributeExchangeProperties = new Dictionary<string, string>();
foreach (var typeProperty in message.Properties.Values)
{
if (typeProperty.Namespace == "http://openid.net/srv/ax/1.0" &&
typeProperty.Name.StartsWith("type."))
if (typeProperty.Namespace != "http://openid.net/srv/ax/1.0" || !typeProperty.Name.StartsWith("type.")) continue;
var name = "value." + typeProperty.Name.Substring("type.".Length) + "http://openid.net/srv/ax/1.0";
Property valueProperty;
if (message.Properties.TryGetValue(name, out valueProperty))
{
string qname = "value." + typeProperty.Name.Substring("type.".Length) + "http://openid.net/srv/ax/1.0";
Property valueProperty;
if (message.Properties.TryGetValue(qname, out valueProperty))
{
attributeExchangeProperties.Add(typeProperty.Value, valueProperty.Value);
}
attributeExchangeProperties.Add(typeProperty.Value, valueProperty.Value);
}
}
@@ -185,14 +168,14 @@ namespace Owin.Security.Providers.OpenID
new XAttribute(XNamespace.Xmlns + "openid.ax", "http://openid.net/srv/ax/1.0")
};
IEnumerable<object> responseProperties = message.Properties
.Where(p => p.Value.Namespace != null)
.Select(p => (object)new XElement(XName.Get(p.Value.Name.Substring(0, p.Value.Name.Length - 1), p.Value.Namespace), p.Value.Value));
var responseProperties = message.Properties
.Where(p => p.Value.Namespace != null)
.Select(p => (object)new XElement(XName.Get(p.Value.Name.Substring(0, p.Value.Name.Length - 1), p.Value.Namespace), p.Value.Value));
var responseMessage = new XElement("response", responseNamespaces.Concat(responseProperties).ToArray());
var identity = new ClaimsIdentity(Options.AuthenticationType);
XElement claimedId = responseMessage.Element(XName.Get("claimed_id", "http://specs.openid.net/auth/2.0"));
var claimedId = responseMessage.Element(XName.Get("claimed_id", "http://specs.openid.net/auth/2.0"));
if (claimedId != null)
{
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, claimedId.Value, "http://www.w3.org/2001/XMLSchema#string", Options.AuthenticationType));
@@ -219,12 +202,10 @@ namespace Owin.Security.Providers.OpenID
return new AuthenticationTicket(context.Identity, context.Properties);
}
return new AuthenticationTicket(null, properties);
}
catch (Exception ex)
{
_logger.WriteError("Authentication failed", ex);
Logger.WriteError("Authentication failed", ex);
return new AuthenticationTicket(null, properties);
}
}
@@ -280,7 +261,7 @@ namespace Owin.Security.Providers.OpenID
private static string GetStateParameter(IReadableStringCollection query)
{
IList<string> values = query.GetValues("state");
var values = query.GetValues("state");
if (values != null && values.Count == 1)
{
return values[0];
@@ -290,7 +271,7 @@ namespace Owin.Security.Providers.OpenID
private AuthenticationProperties UnpackStateParameter(IReadableStringCollection query)
{
string state = GetStateParameter(query);
var state = GetStateParameter(query);
if (state != null)
{
return Options.StateDataFormat.Unprotect(state);
@@ -301,18 +282,15 @@ namespace Owin.Security.Providers.OpenID
private string BuildReturnTo(string state)
{
return Request.Scheme + "://" + Request.Host +
RequestPathBase + Options.CallbackPath +
"?state=" + Uri.EscapeDataString(state);
RequestPathBase + Options.CallbackPath +
"?state=" + Uri.EscapeDataString(state);
}
private async Task<Message> ParseRequestMessageAsync(IReadableStringCollection query)
{
if (Request.Method == "POST")
{
IFormCollection form = await Request.ReadFormAsync();
return new Message(form, strict: true);
}
return new Message(query, strict: true);
if (Request.Method != "POST") return new Message(query, true);
var form = await Request.ReadFormAsync();
return new Message(form, true);
}
protected override async Task ApplyResponseChallengeAsync()
@@ -322,7 +300,7 @@ namespace Owin.Security.Providers.OpenID
return;
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
@@ -333,10 +311,10 @@ namespace Owin.Security.Providers.OpenID
if (!string.IsNullOrEmpty(Options.ProviderLoginUri))
{
string requestPrefix = Request.Scheme + Uri.SchemeDelimiter + Request.Host;
var requestPrefix = Request.Scheme + Uri.SchemeDelimiter + Request.Host;
var state = challenge.Properties;
if (String.IsNullOrEmpty(state.RedirectUri))
if (string.IsNullOrEmpty(state.RedirectUri))
{
state.RedirectUri = requestPrefix + Request.PathBase + Request.Path + Request.QueryString;
}
@@ -344,31 +322,31 @@ namespace Owin.Security.Providers.OpenID
// Anti-CSRF
GenerateCorrelationId(state);
string returnTo = BuildReturnTo(Options.StateDataFormat.Protect(state));
var returnTo = BuildReturnTo(Options.StateDataFormat.Protect(state));
string authorizationEndpoint =
var authorizationEndpoint =
Options.ProviderLoginUri +
"?openid.ns=" + Uri.EscapeDataString("http://specs.openid.net/auth/2.0") +
"&openid.mode=" + Uri.EscapeDataString("checkid_setup") +
"&openid.claimed_id=" + Uri.EscapeDataString("http://specs.openid.net/auth/2.0/identifier_select") +
"&openid.identity=" + Uri.EscapeDataString("http://specs.openid.net/auth/2.0/identifier_select") +
"&openid.return_to=" + Uri.EscapeDataString(returnTo) +
"&openid.realm=" + Uri.EscapeDataString(requestPrefix) +
"?openid.ns=" + Uri.EscapeDataString("http://specs.openid.net/auth/2.0") +
"&openid.mode=" + Uri.EscapeDataString("checkid_setup") +
"&openid.claimed_id=" + Uri.EscapeDataString("http://specs.openid.net/auth/2.0/identifier_select") +
"&openid.identity=" + Uri.EscapeDataString("http://specs.openid.net/auth/2.0/identifier_select") +
"&openid.return_to=" + Uri.EscapeDataString(returnTo) +
"&openid.realm=" + Uri.EscapeDataString(requestPrefix) +
"&openid.ns.ax=" + Uri.EscapeDataString("http://openid.net/srv/ax/1.0") +
"&openid.ax.mode=" + Uri.EscapeDataString("fetch_request") +
"&openid.ns.ax=" + Uri.EscapeDataString("http://openid.net/srv/ax/1.0") +
"&openid.ax.mode=" + Uri.EscapeDataString("fetch_request") +
"&openid.ax.type.email=" + Uri.EscapeDataString("http://axschema.org/contact/email") +
"&openid.ax.type.name=" + Uri.EscapeDataString("http://axschema.org/namePerson") +
"&openid.ax.type.first=" + Uri.EscapeDataString("http://axschema.org/namePerson/first") +
"&openid.ax.type.last=" + Uri.EscapeDataString("http://axschema.org/namePerson/last") +
"&openid.ax.type.email=" + Uri.EscapeDataString("http://axschema.org/contact/email") +
"&openid.ax.type.name=" + Uri.EscapeDataString("http://axschema.org/namePerson") +
"&openid.ax.type.first=" + Uri.EscapeDataString("http://axschema.org/namePerson/first") +
"&openid.ax.type.last=" + Uri.EscapeDataString("http://axschema.org/namePerson/last") +
"&openid.ax.type.email2=" + Uri.EscapeDataString("http://schema.openid.net/contact/email") +
"&openid.ax.type.name2=" + Uri.EscapeDataString("http://schema.openid.net/namePerson") +
"&openid.ax.type.first2=" + Uri.EscapeDataString("http://schema.openid.net/namePerson/first") +
"&openid.ax.type.last2=" + Uri.EscapeDataString("http://schema.openid.net/namePerson/last") +
"&openid.ax.type.email2=" + Uri.EscapeDataString("http://schema.openid.net/contact/email") +
"&openid.ax.type.name2=" + Uri.EscapeDataString("http://schema.openid.net/namePerson") +
"&openid.ax.type.first2=" + Uri.EscapeDataString("http://schema.openid.net/namePerson/first") +
"&openid.ax.type.last2=" + Uri.EscapeDataString("http://schema.openid.net/namePerson/last") +
"&openid.ax.required=" + Uri.EscapeDataString("email,name,first,last,email2,name2,first2,last2");
"&openid.ax.required=" + Uri.EscapeDataString("email,name,first,last,email2,name2,first2,last2");
// allow protocol extensions to add their own attributes to the endpoint URL
var endpoint = new OpenIDAuthorizationEndpointInfo()
@@ -388,22 +366,23 @@ namespace Owin.Security.Providers.OpenID
private async Task DoYadisDiscoveryAsync()
{
// 1° request
HttpResponseMessage httpResponse = await SendRequestAsync(Options.ProviderDiscoveryUri, CONTENTTYPE_XRDS, CONTENTTYPE_HTML, CONTENTTYPE_XHTML);
// 1° request
var httpResponse = await SendRequestAsync(Options.ProviderDiscoveryUri, ContenttypeXrds, ContenttypeHTML, ContenttypeXhtml);
if (httpResponse.StatusCode != HttpStatusCode.OK)
{
_logger.WriteError(string.Format("HTTP error {0} ({1}) while performing discovery on {2}.", (int)httpResponse.StatusCode, httpResponse.StatusCode, Options.ProviderDiscoveryUri));
Logger.WriteError(
$"HTTP error {(int) httpResponse.StatusCode} ({httpResponse.StatusCode}) while performing discovery on {Options.ProviderDiscoveryUri}.");
return;
}
await httpResponse.Content.LoadIntoBufferAsync();
// 2° request (if necessary)
// 2° request (if necessary)
if (!await IsXrdsDocumentAsync(httpResponse))
{
IEnumerable<string> uriStrings;
string uriString = null;
if (httpResponse.Headers.TryGetValues(XRDS_LOCATIONHEADER, out uriStrings))
if (httpResponse.Headers.TryGetValues(XrdsLocationheader, out uriStrings))
{
uriString = uriStrings.FirstOrDefault();
}
@@ -415,76 +394,64 @@ namespace Owin.Security.Providers.OpenID
}
var contentType = httpResponse.Content.Headers.ContentType;
if (url == null && contentType != null && (contentType.MediaType == CONTENTTYPE_HTML || contentType.MediaType == CONTENTTYPE_XHTML))
if (url == null && contentType != null && (contentType.MediaType == ContenttypeHTML || contentType.MediaType == ContenttypeXhtml))
{
url = FindYadisDocumentLocationInHtmlMetaTags(await httpResponse.Content.ReadAsStringAsync());
}
if (url == null)
{
_logger.WriteError(string.Format("The uri {0} doesn't return an XRDS document.", Options.ProviderDiscoveryUri));
Logger.WriteError($"The uri {Options.ProviderDiscoveryUri} doesn't return an XRDS document.");
return;
}
else
{
httpResponse = await SendRequestAsync(url.AbsoluteUri, CONTENTTYPE_XRDS);
httpResponse = await SendRequestAsync(url.AbsoluteUri, ContenttypeXrds);
if (httpResponse.StatusCode != HttpStatusCode.OK)
{
_logger.WriteError(string.Format("HTTP error {0} {1} while performing discovery on {2}.", (int)httpResponse.StatusCode, httpResponse.StatusCode, url.AbsoluteUri));
Logger.WriteError(
$"HTTP error {(int) httpResponse.StatusCode} {httpResponse.StatusCode} while performing discovery on {url.AbsoluteUri}.");
return;
}
if (!await IsXrdsDocumentAsync(httpResponse))
{
_logger.WriteError(string.Format("The uri {0} doesn't return an XRDS document.", url.AbsoluteUri));
Logger.WriteError($"The uri {url.AbsoluteUri} doesn't return an XRDS document.");
return;
}
}
}
// Get provider url from XRDS document
XDocument xrdsDoc = XDocument.Parse(await httpResponse.Content.ReadAsStringAsync());
var xrdsDoc = XDocument.Parse(await httpResponse.Content.ReadAsStringAsync());
Options.ProviderLoginUri = xrdsDoc.Root.Element(XName.Get("XRD", "xri://$xrd*($v*2.0)"))
.Descendants(XName.Get("Service", "xri://$xrd*($v*2.0)"))
.Where(service => service.Descendants(XName.Get("Type", "xri://$xrd*($v*2.0)")).Any(type => type.Value == "http://specs.openid.net/auth/2.0/server"))
.OrderBy(service =>
{
var priorityAttribute = service.Attribute("priority");
if (priorityAttribute == null)
return null;
return priorityAttribute.Value;
return priorityAttribute?.Value;
})
.Select(service => service.Element(XName.Get("URI", "xri://$xrd*($v*2.0)")).Value)
.FirstOrDefault();
}
// FIXME use an HTTP parser
private static readonly Regex MetaTagXRDSLocationRegex = new Regex(@"<meta http-equiv=""X-XRDS-Location"" content=""(.*?)"">", RegexOptions.Compiled);
private static Uri FindYadisDocumentLocationInHtmlMetaTags(string html)
{
var match = MetaTagXRDSLocationRegex.Match(html);
if (match.Success)
{
Uri uri;
if (Uri.TryCreate(match.Groups[1].Value, UriKind.Absolute, out uri))
{
return uri;
}
}
return null;
var match = new Regex(@"<meta http-equiv=""X-XRDS-Location"" content=""(.*?)"">", RegexOptions.Compiled).Match(html);
if (!match.Success) return null;
Uri uri;
return Uri.TryCreate(match.Groups[1].Value, UriKind.Absolute, out uri) ? uri : null;
}
private async Task<HttpResponseMessage> SendRequestAsync(string uri, params string[] acceptTypes)
{
HttpRequestMessage httprequest = new HttpRequestMessage(HttpMethod.Get, uri);
if (acceptTypes != null)
var httprequest = new HttpRequestMessage(HttpMethod.Get, uri);
if (acceptTypes == null) return await HTTPClient.SendAsync(httprequest);
foreach (var acceptType in acceptTypes)
{
foreach (string acceptType in acceptTypes)
{
httprequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(acceptType));
}
httprequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(acceptType));
}
return await _httpClient.SendAsync(httprequest);
return await HTTPClient.SendAsync(httprequest);
}
private static async Task<bool> IsXrdsDocumentAsync(HttpResponseMessage response)
@@ -494,23 +461,21 @@ namespace Owin.Security.Providers.OpenID
return false;
}
if (response.Content.Headers.ContentType.MediaType == CONTENTTYPE_XRDS)
if (response.Content.Headers.ContentType.MediaType == ContenttypeXrds)
{
return true;
}
if (response.Content.Headers.ContentType.MediaType == CONTENTTYPE_XML)
if (response.Content.Headers.ContentType.MediaType != ContenttypeXml) return false;
using (var responseStream = await response.Content.ReadAsStreamAsync())
{
using (var responseStream = await response.Content.ReadAsStreamAsync())
{
XmlReader reader = XmlReader.Create(responseStream, new XmlReaderSettings { MaxCharactersFromEntities = 1024, XmlResolver = null, DtdProcessing = DtdProcessing.Prohibit });
var reader = XmlReader.Create(responseStream, new XmlReaderSettings { MaxCharactersFromEntities = 1024, XmlResolver = null, DtdProcessing = DtdProcessing.Prohibit });
while (await reader.ReadAsync() && reader.NodeType != XmlNodeType.Element)
{ }
if (reader.NamespaceURI == XRD_NAMESPACE && reader.Name == "XRDS")
{
return true;
}
while (await reader.ReadAsync() && reader.NodeType != XmlNodeType.Element)
{ }
if (reader.NamespaceURI == XrdNamespace && reader.Name == "XRDS")
{
return true;
}
}
@@ -519,24 +484,26 @@ namespace Owin.Security.Providers.OpenID
public async Task<bool> InvokeReturnPathAsync()
{
AuthenticationTicket model = await AuthenticateAsync();
var model = await AuthenticateAsync();
if (model == null)
{
_logger.WriteWarning("Invalid return state, unable to redirect.");
Logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new OpenIDReturnEndpointContext(Context, model);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = model.Properties.RedirectUri;
var context = new OpenIDReturnEndpointContext(Context, model)
{
SignInAsAuthenticationType = Options.SignInAsAuthenticationType,
RedirectUri = model.Properties.RedirectUri
};
model.Properties.RedirectUri = null;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null && context.Identity != null)
{
ClaimsIdentity signInIdentity = context.Identity;
var signInIdentity = context.Identity;
if (!string.Equals(signInIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
signInIdentity = new ClaimsIdentity(signInIdentity.Claims, context.SignInAsAuthenticationType, signInIdentity.NameClaimType, signInIdentity.RoleClaimType);
@@ -544,18 +511,16 @@ namespace Owin.Security.Providers.OpenID
Context.Authentication.SignIn(context.Properties, signInIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
if (context.IsRequestCompleted || context.RedirectUri == null) return context.IsRequestCompleted;
if (context.Identity == null)
{
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
context.RedirectUri = WebUtilities.AddQueryString(context.RedirectUri, "error", "access_denied");
}
Response.Redirect(context.RedirectUri);
context.RequestCompleted();
// add a redirect hint that sign-in failed in some way
context.RedirectUri = WebUtilities.AddQueryString(context.RedirectUri, "error", "access_denied");
}
Response.Redirect(context.RedirectUri);
context.RequestCompleted();
return context.IsRequestCompleted;
}
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Globalization;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
namespace Owin.Security.Providers.OpenIDBase
{
/// <summary>
/// OWIN middleware for authenticating users using an OpenID provider
/// </summary>
public abstract class OpenIDAuthenticationMiddlewareBase<T> : AuthenticationMiddleware<T> where T : OpenIDAuthenticationOptions
{
protected readonly ILogger Logger;
protected readonly HttpClient HTTPClient;
/// <summary>
/// Initializes a <see cref="OpenIDAuthenticationMiddlewareBase{T}"/>
/// </summary>
/// <param name="next">The next middleware in the OWIN pipeline to invoke</param>
/// <param name="app">The OWIN application</param>
/// <param name="options">Configuration options for the middleware</param>
protected OpenIDAuthenticationMiddlewareBase(OwinMiddleware next, IAppBuilder app, T options)
: base(next, options)
{
if (string.IsNullOrWhiteSpace(Options.ProviderDiscoveryUri) && string.IsNullOrWhiteSpace(Options.ProviderLoginUri) && Options.AuthenticationType != Constants.DefaultAuthenticationType)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "ProviderDiscoveryUri"));
}
Logger = app.CreateLogger<OpenIDAuthenticationMiddlewareBase<T>>();
if (Options.Provider == null) Options.Provider = new OpenIDAuthenticationProvider();
if (Options.StateDataFormat == null)
{
var dataProtecter = app.CreateDataProtector(typeof(OpenIDAuthenticationMiddlewareBase<T>).FullName, Options.AuthenticationType, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtecter);
}
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
{
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
}
HTTPClient = new HttpClient(ResolveHttpMessageHandler(Options))
{
Timeout = Options.BackchannelTimeout,
MaxResponseContentBufferSize = 1024*1024*10
};
// 10 MB
}
/// <summary>
/// Provides the <see cref="AuthenticationHandler"/> object for processing authentication-related requests.
/// </summary>
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OpenIDAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<T> CreateHandler()
{
return CreateSpecificHandler();
}
/// <summary>
/// Provides the <see cref="AuthenticationHandler"/> object for processing authentication-related requests.
/// </summary>
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OpenIDAuthenticationOptions"/> supplied to the constructor.</returns>
protected abstract AuthenticationHandler<T> CreateSpecificHandler();
private static HttpMessageHandler ResolveHttpMessageHandler(OpenIDAuthenticationOptions options)
{
var handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator == null) return handler;
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
return handler;
}
}
}

View File

@@ -4,11 +4,8 @@ using Microsoft.Owin.Security;
using System;
using System.Net.Http;
namespace Owin.Security.Providers.OpenID
namespace Owin.Security.Providers.OpenIDBase
{
/// <summary>
/// Configuration options for <see cref="OpenIDAuthenticationMiddleware"/>
/// </summary>
public class OpenIDAuthenticationOptions : AuthenticationOptions
{
/// <summary>
@@ -87,8 +84,7 @@ namespace Owin.Security.Providers.OpenID
/// <summary>
/// Initializes a new <see cref="OpenIDAuthenticationOptions"/>
/// </summary>
public OpenIDAuthenticationOptions()
: base(Constants.DefaultAuthenticationType)
public OpenIDAuthenticationOptions() : base(Constants.DefaultAuthenticationType)
{
Caption = Constants.DefaultAuthenticationType;
CallbackPath = new PathString("/signin-openid");

View File

@@ -0,0 +1,9 @@
namespace Owin.Security.Providers.OpenIDBase
{
public class OpenIDAuthorizationEndpointInfo
{
public string Url { get; set; }
}
}

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4FD7B873-1994-4990-AA40-C37060121494}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.OpenIDBase</RootNamespace>
<AssemblyName>Owin.Security.Providers.OpenIDBase</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Constants.cs" />
<Compile Include="Extensions\OpenIDSimpleRegistrationAuthenticationContextExtensions.cs" />
<Compile Include="Extensions\OpenIDSimpleRegistrationExtension.cs" />
<Compile Include="Extensions\OpenIDSimpleRegistrationField.cs" />
<Compile Include="Extensions\OpenIDSimpleRegistrationResult.cs" />
<Compile Include="Infrastructure\Message.cs" />
<Compile Include="Infrastructure\Property.cs" />
<Compile Include="IOpenIDProtocolExtension.cs" />
<Compile Include="OpenIDAuthenticationHandlerBase.cs" />
<Compile Include="OpenIDAuthenticationMiddlewareBase.cs" />
<Compile Include="OpenIDAuthenticationOptions.cs" />
<Compile Include="OpenIDAuthorizationEndpointInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Provider\IOpenIDAuthenticationProvider.cs" />
<Compile Include="Provider\OpenIDAuthenticatedContext.cs" />
<Compile Include="Provider\OpenIDAuthenticationProvider.cs" />
<Compile Include="Provider\OpenIDReturnEndpointContext.cs" />
<Compile Include="Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Owin.Security.Providers.OpenIDBase</id>
<version>2.0</version>
<authors>Jerrie Pelser, Tommy Parnell and contributors</authors>
<owners>Tommy Parnell</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>https://github.com/tparnell8/OwinOAuthProviders</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Adds additional OAuth providers for OWIN to use with ASP.NET
</description>
<summary>
Additional OAuth providers for Katana (OWIN).
Includes providers for ArcGISOnline, Asana, Backlog, Battle.net, Bitbucket, Buffer, DeviantArt, Dropbox, EVEOnline, Fitbit, Flickr, Foursquare, GitHub, Gitter, Google+, HealthGraph, Imgur, Instagram, LinkedIn, Onshape, PayPal, Reddit, Salesforce, Slack, SoundCloud, Spotify, StackExchange, TripIt, Twitch.tv, Untappd, Vimeo, Visual Studio Online, VKontakte, Wordpress, Yahoo and Yammer.
Also adds generic OpenID 2.0 providers as well implementations for Steam and Wargaming.
</summary>
<releaseNotes>
Version 2.0
- Decouple providers into individual files
</releaseNotes>
<copyright>Copyright 2013 - 2016</copyright>
<tags>owin katana oauth LinkedIn Yahoo Google+ GitHub Reddit Instagram StackExchange SalesForce TripIt Buffer ArcGIS Dropbox Wordpress Battle.NET Yammer OpenID Steam Twitch</tags>
</metadata>
</package>

View File

@@ -0,0 +1,18 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Owin.Security.Providers.OpenIDBaseBase")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.OpenIDBaseBase")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("4fd7b873-1994-4990-aa40-c37060121494")]
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

View File

@@ -1,14 +1,11 @@
using System.Threading.Tasks;
namespace Owin.Security.Providers.OpenID
namespace Owin.Security.Providers.OpenIDBase
{
/// <summary>
/// Specifies callback methods which the <see cref="OpenIDAuthenticationMiddleware"></see> invokes to enable developer control over the authentication process. />
/// </summary>
public interface IOpenIDAuthenticationProvider
{
/// <summary>
/// Invoked whenever OpenID succesfully authenticates a user
/// Invoked whenever OpenID successfully authenticates a user
/// </summary>
/// <param name="context">Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.</param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>

View File

@@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Security.Claims;
using System.Xml.Linq;
namespace Owin.Security.Providers.OpenID
namespace Owin.Security.Providers.OpenIDBase
{
/// <summary>
/// Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.

View File

@@ -1,7 +1,7 @@
using System;
using System.Threading.Tasks;
namespace Owin.Security.Providers.OpenID
namespace Owin.Security.Providers.OpenIDBase
{
/// <summary>
/// Default <see cref="IOpenIDAuthenticationProvider"/> implementation.
@@ -28,7 +28,7 @@ namespace Owin.Security.Providers.OpenID
public Func<OpenIDReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever OpenID succesfully authenticates a user
/// Invoked whenever OpenID successfully authenticates a user
/// </summary>
/// <param name="context">Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.</param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>

View File

@@ -2,7 +2,7 @@
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Provider;
namespace Owin.Security.Providers.OpenID
namespace Owin.Security.Providers.OpenIDBase
{
/// <summary>
/// Provides context information to middleware providers.

View File

@@ -1,14 +1,14 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34003
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Owin.Security.Providers.Properties {
namespace Owin.Security.Providers.OpenIDBase {
using System;
@@ -39,7 +39,7 @@ namespace Owin.Security.Providers.Properties {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Owin.Security.Providers.Properties.Resources", typeof(Resources).Assembly);
var temp = new global::System.Resources.ResourceManager("Owin.Security.Providers.OpenIDBase.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net452" />
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" />
</packages>

1
base/Readme.md Normal file
View File

@@ -0,0 +1 @@
Base libraries independently versioned go here...things that versions should be better (ie..manually) managed and what not

30
global.nuspec.erb Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Owin.Security.Providers</id>
<version><%= @version %></version>
<authors>Jerrie Pelser, Tommy Parnell and contributors</authors>
<owners>Tommy Parnell</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>https://github.com/tparnell8/OwinOAuthProviders</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Adds additional OAuth providers for OWIN to use with ASP.NET
</description>
<summary>
Additional OAuth providers for Katana (OWIN).
There are many individual providers, this package is a meta package that has a dependency on all of them.
</summary>
<releaseNotes>
Version 2.0
- Decouple providers into individual files
</releaseNotes>
<copyright>Copyright 2013 - 2016</copyright>
<tags>owin katana oauth LinkedIn Yahoo Google+ GitHub Reddit Instagram StackExchange SalesForce TripIt Buffer ArcGIS Dropbox Wordpress Battle.NET Yammer OpenID Steam Twitch</tags>
<dependencies>
<% for @item in @nugets %>
<dependency id="<%= @item %>" version="<%= @version %>" />
<% end %>
</dependencies>
</metadata>
</package>

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014 Jerrie Pelser
Copyright (c) 2014, 2015 Jerrie Pelser
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

44
nuget.rake Normal file
View File

@@ -0,0 +1,44 @@
namespace :nuget do
# If we don't have a copy of nuget, download it
task :bootstrap do
puts 'Ensuring NuGet exists in tools/NuGet'
if !FileTest.exist?("#{NUGET}/nuget.exe")
puts 'Downloading nuget from nuget.org'
begin
FileUtils.mkdir_p("#{NUGET}")
File.open("#{NUGET}/nuget.exe", "wb") do |file|
file.write open('http://nuget.org/nuget.exe', {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
end
rescue
FileUtils.rm_rf("#{NUGET}/nuget.exe")
File.open("#{NUGET}/nuget.exe", "wb") do |file|
file.write open('https://dist.nuget.org/win-x86-commandline/v3.2.0/nuget.exe', {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
end
end
end
end
desc 'Fetch nuget dependencies for all packages'
task :fetch => :bootstrap do
# If we aren't running under windows, assume we're using mono
CMD_PREFIX = ""
if !OS.windows?
CMD_PREFIX = "mono"
begin
sh "mozroots --import --sync" #attempt to sync ssl things...
rescue
end
end
# Make sure we get solution-level deps
#sh "#{CMD_PREFIX} #{NUGET}/nuget.exe i .nuget/packages.config -o packages"
FileList["src/**/packages.config"].each { |filepath|
sh "#{CMD_PREFIX} #{NUGET}/nuget.exe restore"
}
end
end

BIN
nuget/NuGet.exe Normal file

Binary file not shown.

28
nuspectemplate.nuspec.erb Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0"?>
<package >
<metadata>
<id><%= @id %></id>
<version><%= @version %></version>
<authors>Jerrie Pelser, Tommy Parnell and contributors</authors>
<owners>Tommy Parnell</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>https://github.com/tparnell8/OwinOAuthProviders</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Adds additional OAuth providers for OWIN to use with ASP.NET
</description>
<summary>
Additional OAuth providers for Katana (OWIN).
Includes providers for ArcGISOnline, Asana, Backlog, Battle.net, Bitbucket, Buffer, DeviantArt, Dropbox, EVEOnline, Fitbit, Flickr, Foursquare, GitHub, Gitter, Google+, HealthGraph, Imgur, Instagram, LinkedIn, Onshape, PayPal, Reddit, Salesforce, Slack, SoundCloud, Spotify, StackExchange, TripIt, Twitch.tv, Untappd, Vimeo, Visual Studio Online, VKontakte, Wordpress, Yahoo and Yammer.
Also adds generic OpenID 2.0 providers as well implementations for Steam and Wargaming.
</summary>
<releaseNotes>
Version 2.0
- Decouple providers into individual files
</releaseNotes>
<copyright>Copyright 2013 - 2016</copyright>
<tags>owin katana oauth LinkedIn Yahoo Google+ GitHub Reddit Instagram StackExchange SalesForce TripIt Buffer ArcGIS Dropbox Wordpress Battle.NET Yammer OpenID Steam Twitch</tags>
</metadata>
</package>

View File

@@ -8,9 +8,9 @@ namespace Owin.Security.Providers.ArcGISOnline
ArcGISOnlineAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException("app");
throw new ArgumentNullException(nameof(app));
if (options == null)
throw new ArgumentNullException("options");
throw new ArgumentNullException(nameof(options));
app.Use(typeof(ArcGISOnlineAuthenticationMiddleware), app, options);

View File

@@ -0,0 +1,231 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
namespace Owin.Security.Providers.ArcGISOnline
{
public class ArcGISOnlineAuthenticationHandler : AuthenticationHandler<ArcGISOnlineAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public ArcGISOnlineAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
_httpClient = httpClient;
_logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
var query = Request.Query;
var values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties,_logger))
{
return new AuthenticationTicket(null, properties);
}
var requestPrefix = Request.Scheme + "://" + Request.Host;
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
new KeyValuePair<string, string>("client_id", Options.ClientId),
new KeyValuePair<string, string>("client_secret", Options.ClientSecret)
};
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
var tokenResponse = await _httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
var text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
var accessToken = (string)response.access_token;
// Get the ArcGISOnline user
var userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?f=json&token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var userResponse = await _httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
var user = JsonConvert.DeserializeObject<Provider.ArcGISOnlineUser>(text);
var context = new ArcGISOnlineAuthenticatedContext(Context, user, accessToken)
{
Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType)
};
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim("urn:ArcGISOnline:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:ArcGISOnline:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
_logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge == null) return Task.FromResult<object>(null);
var baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
var currentUri =
baseUri +
Request.Path +
Request.QueryString;
var redirectUri =
baseUri +
Options.CallbackPath;
var properties=challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
GenerateCorrelationId(properties);
var state = Options.StateDataFormat.Protect(properties);
// comma separated
var scope = string.Join(",", Options.Scope);
var authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&response_type=" + Uri.EscapeDataString(scope) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (!Options.CallbackPath.HasValue || Options.CallbackPath != Request.Path) return false;
// TODO: error responses
var ticket = await AuthenticateAsync();
if (ticket == null)
{
_logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new ArcGISOnlineReturnEndpointContext(Context, ticket)
{
SignInAsAuthenticationType = Options.SignInAsAuthenticationType,
RedirectUri = ticket.Properties.RedirectUri
};
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
var grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (context.IsRequestCompleted || context.RedirectUri == null) return context.IsRequestCompleted;
var redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
return context.IsRequestCompleted;
}
}
}

View File

@@ -7,49 +7,48 @@ using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Properties;
namespace Owin.Security.Providers.ArcGISOnline
{
public class ArcGISOnlineAuthenticationMiddleware : AuthenticationMiddleware<ArcGISOnlineAuthenticationOptions>
{
private readonly HttpClient httpClient;
private readonly ILogger logger;
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public ArcGISOnlineAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app,
ArcGISOnlineAuthenticationOptions options)
: base(next, options)
{
if (String.IsNullOrWhiteSpace(Options.ClientId))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
if (string.IsNullOrWhiteSpace(Options.ClientId))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientId"));
if (String.IsNullOrWhiteSpace(Options.ClientSecret))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
if (string.IsNullOrWhiteSpace(Options.ClientSecret))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientSecret"));
logger = app.CreateLogger<ArcGISOnlineAuthenticationMiddleware>();
_logger = app.CreateLogger<ArcGISOnlineAuthenticationMiddleware>();
if (Options.Provider == null)
Options.Provider = new ArcGISOnlineAuthenticationProvider();
if (Options.StateDataFormat == null)
{
IDataProtector dataProtector = app.CreateDataProtector(
var dataProtector = app.CreateDataProtector(
typeof (ArcGISOnlineAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v2");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (String.IsNullOrEmpty(Options.SignInAsAuthenticationType))
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
{
Timeout = Options.BackchannelTimeout,
MaxResponseContentBufferSize = 1024*1024*10,
};
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin ArcGISOnline middleware");
httpClient.DefaultRequestHeaders.ExpectContinue = false;
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin ArcGISOnline middleware");
_httpClient.DefaultRequestHeaders.ExpectContinue = false;
}
/// <summary>
@@ -62,24 +61,22 @@ namespace Owin.Security.Providers.ArcGISOnline
/// </returns>
protected override AuthenticationHandler<ArcGISOnlineAuthenticationOptions> CreateHandler()
{
return new ArcGISOnlineAuthenticationHandler(httpClient, logger);
return new ArcGISOnlineAuthenticationHandler(_httpClient, _logger);
}
private HttpMessageHandler ResolveHttpMessageHandler(ArcGISOnlineAuthenticationOptions options)
private static HttpMessageHandler ResolveHttpMessageHandler(ArcGISOnlineAuthenticationOptions options)
{
HttpMessageHandler handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
var handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator != null)
if (options.BackchannelCertificateValidator == null) return handler;
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
return handler;
}

View File

@@ -123,8 +123,7 @@ namespace Owin.Security.Providers.ArcGISOnline
/// <summary>
/// Initializes a new <see cref="ArcGISOnlineAuthenticationOptions" />
/// </summary>
public ArcGISOnlineAuthenticationOptions()
: base("ArcGIS Online")
public ArcGISOnlineAuthenticationOptions() : base("ArcGIS Online")
{
Caption = Constants.DefaultAuthenticationType;
CallbackPath = new PathString("/signin-arcgis-online");

View File

@@ -2,6 +2,6 @@
{
internal static class Constants
{
public const string DefaultAuthenticationType = "ArcGIS Online";
internal const string DefaultAuthenticationType = "ArcGIS Online";
}
}

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8A49FAEF-D365-4D25-942C-1CAD03845A5E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.ArcGISOnline</RootNamespace>
<AssemblyName>Owin.Security.Providers.ArcGISOnline</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArcGISOnlineAuthenticationExtensions.cs" />
<Compile Include="ArcGISOnlineAuthenticationHandler.cs" />
<Compile Include="ArcGISOnlineAuthenticationMiddleware.cs" />
<Compile Include="ArcGISOnlineAuthenticationOptions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Provider\ArcGISOnlineAuthenticatedContext.cs" />
<Compile Include="Provider\ArcGISOnlineAuthenticationProvider.cs" />
<Compile Include="Provider\ArcGISOnlineReturnEndpointContext.cs" />
<Compile Include="Provider\ArcGISOnlineUser.cs" />
<Compile Include="Provider\IArcGISOnlineAuthenticationProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity>
<ItemGroup>
<VersionNumber Include="@(Targets->'%(Version)')" />
</ItemGroup>
</Target>
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,15 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Owin.Security.Providers.ArcGISOnline")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.ArcGISOnline")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("edf75484-ed98-4f6c-bd71-f4d8fa3fc019")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

View File

@@ -1,13 +1,9 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Security.Claims;
using System.Linq;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Provider;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.ArcGISOnline.Provider;
namespace Owin.Security.Providers.ArcGISOnline
@@ -28,11 +24,11 @@ namespace Owin.Security.Providers.ArcGISOnline
{
AccessToken = accessToken;
Id = user.user.username;
Name = user.user.fullName;
Id = user.User.Username;
Name = user.User.FullName;
Link = "https://www.arcgis.com/sharing/rest/community/users/" + Id;
UserName = Id;
Email = user.user.email;
Email = user.User.Email;
}
/// <summary>
@@ -43,7 +39,7 @@ namespace Owin.Security.Providers.ArcGISOnline
/// <summary>
/// Gets the ArcGISOnline user ID
/// </summary>
public string Id { get; private set; }
public string Id { get; }
/// <summary>
/// Gets the user's name

View File

@@ -28,7 +28,7 @@ namespace Owin.Security.Providers.ArcGISOnline
public Func<ArcGISOnlineReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever ArcGISOnline succesfully authenticates a user
/// Invoked whenever ArcGISOnline successfully authenticates a user
/// </summary>
/// <param name="context">Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.</param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>

View File

@@ -0,0 +1,14 @@
namespace Owin.Security.Providers.ArcGISOnline.Provider
{
public class ArcGISOnlineUser
{
public User User { get; set; }
}
public class User
{
public string Username { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
}
}

View File

@@ -8,7 +8,7 @@ namespace Owin.Security.Providers.ArcGISOnline
public interface IArcGISOnlineAuthenticationProvider
{
/// <summary>
/// Invoked whenever ArcGISOnline succesfully authenticates a user
/// Invoked whenever ArcGISOnline successfully authenticates a user
/// </summary>
/// <param name="context">Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.</param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>

View File

@@ -0,0 +1,81 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Owin.Security.Providers.ArcGISOnline {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
var temp = new global::System.Resources.ResourceManager("Owin.Security.Providers.ArcGISOnline.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;{0}&apos; option must be provided..
/// </summary>
internal static string Exception_OptionMustBeProvided {
get {
return ResourceManager.GetString("Exception_OptionMustBeProvided", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An ICertificateValidator cannot be specified at the same time as an HttpMessageHandler unless it is a WebRequestHandler..
/// </summary>
internal static string Exception_ValidatorHandlerMismatch {
get {
return ResourceManager.GetString("Exception_ValidatorHandlerMismatch", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Exception_OptionMustBeProvided" xml:space="preserve">
<value>The '{0}' option must be provided.</value>
</data>
<data name="Exception_ValidatorHandlerMismatch" xml:space="preserve">
<value>An ICertificateValidator cannot be specified at the same time as an HttpMessageHandler unless it is a WebRequestHandler.</value>
</data>
</root>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net452" />
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" />
</packages>

View File

@@ -8,9 +8,9 @@ namespace Owin.Security.Providers.Asana
AsanaAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException("app");
throw new ArgumentNullException(nameof(app));
if (options == null)
throw new ArgumentNullException("options");
throw new ArgumentNullException(nameof(options));
app.Use(typeof(AsanaAuthenticationMiddleware), app, options);

View File

@@ -4,13 +4,11 @@ using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.Asana
{
@@ -18,13 +16,13 @@ namespace Owin.Security.Providers.Asana
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public AsanaAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
_httpClient = httpClient;
_logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
@@ -36,8 +34,8 @@ namespace Owin.Security.Providers.Asana
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
var query = Request.Query;
var values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
@@ -55,21 +53,23 @@ namespace Owin.Security.Providers.Asana
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
if (!ValidateCorrelationId(properties, _logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
var requestPrefix = Request.Scheme + "://" + Request.Host;
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("code", code));
var body = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("client_id", Options.ClientId),
new KeyValuePair<string, string>("client_secret", Options.ClientSecret),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
new KeyValuePair<string, string>("code", code)
};
/*Your app makes a POST request to https://app.asana.com/-/oauth_token, passing the parameters as part of a standard form-encoded post body.
grant_type - required Must be authorization_code
@@ -83,13 +83,13 @@ namespace Owin.Security.Providers.Asana
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
var tokenResponse = await _httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
var text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
var accessToken = (string)response.access_token;
/*
* In the response, you will receive a JSON payload with the following parameters:
@@ -102,11 +102,13 @@ namespace Owin.Security.Providers.Asana
// Get the Asana user
var context = new AsanaAuthenticatedContext(Context, response.data, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
var context = new AsanaAuthenticatedContext(Context, response.data, accessToken)
{
Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType)
};
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
@@ -127,7 +129,7 @@ namespace Owin.Security.Providers.Asana
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
_logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
@@ -139,45 +141,44 @@ namespace Owin.Security.Providers.Asana
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
if (challenge == null) return Task.FromResult<object>(null);
var baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
var currentUri =
baseUri +
Request.Path +
Request.QueryString;
var redirectUri =
baseUri +
Options.CallbackPath;
var properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
properties.RedirectUri = currentUri;
}
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state)
;
var state = Options.StateDataFormat.Protect(properties);
var authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state)
;
/*Your app redirects the user to https://app.asana.com/-/oauth_authorize, passing parameters along as a standard query string:
/*Your app redirects the user to https://app.asana.com/-/oauth_authorize, passing parameters along as a standard query string:
client_id - required The Client ID uniquely identifies the application making the request.
redirect_uri - required The URI to redirect to on success or error. This must match the Redirect URL specified in the application settings.
@@ -185,8 +186,7 @@ namespace Owin.Security.Providers.Asana
state - optional Encodes state of the app, which will be returned verbatim in the response and can be used to match the response up to a given request.
*/
Response.Redirect(authorizationEndpoint);
}
Response.Redirect(authorizationEndpoint);
return Task.FromResult<object>(null);
}
@@ -198,50 +198,47 @@ namespace Owin.Security.Providers.Asana
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
if (!Options.CallbackPath.HasValue || Options.CallbackPath != Request.Path) return false;
// TODO: error responses
var ticket = await AuthenticateAsync();
if (ticket == null)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new AsanaReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (!context.IsRequestCompleted && context.RedirectUri != null)
{
string redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
}
return context.IsRequestCompleted;
_logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
return false;
var context = new AsanaReturnEndpointContext(Context, ticket)
{
SignInAsAuthenticationType = Options.SignInAsAuthenticationType,
RedirectUri = ticket.Properties.RedirectUri
};
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
var grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (context.IsRequestCompleted || context.RedirectUri == null) return context.IsRequestCompleted;
var redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
return context.IsRequestCompleted;
}
}
}

View File

@@ -7,49 +7,48 @@ using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Properties;
namespace Owin.Security.Providers.Asana
{
public class AsanaAuthenticationMiddleware : AuthenticationMiddleware<AsanaAuthenticationOptions>
{
private readonly HttpClient httpClient;
private readonly ILogger logger;
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public AsanaAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app,
AsanaAuthenticationOptions options)
: base(next, options)
{
if (String.IsNullOrWhiteSpace(Options.ClientId))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
if (string.IsNullOrWhiteSpace(Options.ClientId))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientId"));
if (String.IsNullOrWhiteSpace(Options.ClientSecret))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
if (string.IsNullOrWhiteSpace(Options.ClientSecret))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientSecret"));
logger = app.CreateLogger<AsanaAuthenticationMiddleware>();
_logger = app.CreateLogger<AsanaAuthenticationMiddleware>();
if (Options.Provider == null)
Options.Provider = new AsanaAuthenticationProvider();
if (Options.StateDataFormat == null)
{
IDataProtector dataProtector = app.CreateDataProtector(
var dataProtector = app.CreateDataProtector(
typeof (AsanaAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (String.IsNullOrEmpty(Options.SignInAsAuthenticationType))
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
{
Timeout = Options.BackchannelTimeout,
MaxResponseContentBufferSize = 1024*1024*10,
};
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin Asana middleware");
httpClient.DefaultRequestHeaders.ExpectContinue = false;
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin Asana middleware");
_httpClient.DefaultRequestHeaders.ExpectContinue = false;
}
/// <summary>
@@ -62,24 +61,22 @@ namespace Owin.Security.Providers.Asana
/// </returns>
protected override AuthenticationHandler<AsanaAuthenticationOptions> CreateHandler()
{
return new AsanaAuthenticationHandler(httpClient, logger);
return new AsanaAuthenticationHandler(_httpClient, _logger);
}
private HttpMessageHandler ResolveHttpMessageHandler(AsanaAuthenticationOptions options)
private static HttpMessageHandler ResolveHttpMessageHandler(AsanaAuthenticationOptions options)
{
HttpMessageHandler handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
var handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator != null)
if (options.BackchannelCertificateValidator == null) return handler;
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
return handler;
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Security;

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F3E27220-1D8C-4037-94AA-7B7F4A12F351}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.Asana</RootNamespace>
<AssemblyName>Owin.Security.Providers.Asana</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AsanaAuthenticationExtensions.cs" />
<Compile Include="AsanaAuthenticationHandler.cs" />
<Compile Include="AsanaAuthenticationMiddleware.cs" />
<Compile Include="AsanaAuthenticationOptions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Provider\AsanaAuthenticatedContext.cs" />
<Compile Include="Provider\AsanaAuthenticationProvider.cs" />
<Compile Include="Provider\AsanaReturnEndpointContext.cs" />
<Compile Include="Provider\IAsanaAuthenticationProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity>
<ItemGroup>
<VersionNumber Include="@(Targets->'%(Version)')" />
</ItemGroup>
</Target>
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
</PropertyGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More