();
24 | });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:5051",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "Come.AspNetCore.Sample": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Builder;
6 | using Microsoft.AspNetCore.Hosting;
7 | using Microsoft.Extensions.Configuration;
8 | using Microsoft.Extensions.DependencyInjection;
9 | using Microsoft.Extensions.Hosting;
10 |
11 | namespace Come.AspNetCore.Sample
12 | {
13 | public class Startup
14 | {
15 | public Startup(IConfiguration configuration)
16 | {
17 | Configuration = configuration;
18 | }
19 |
20 | public IConfiguration Configuration { get; }
21 |
22 | // This method gets called by the runtime. Use this method to add services to the container.
23 | public void ConfigureServices(IServiceCollection services)
24 | {
25 | services.AddControllersWithViews();
26 | }
27 |
28 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
29 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
30 | {
31 | if (env.IsDevelopment())
32 | {
33 | app.UseDeveloperExceptionPage();
34 | }
35 | else
36 | {
37 | app.UseExceptionHandler("/Home/Error");
38 | }
39 | app.UseStaticFiles();
40 |
41 | app.UseRouting();
42 |
43 | app.UseAuthorization();
44 |
45 | app.UseEndpoints(endpoints =>
46 | {
47 | endpoints.MapControllerRoute(
48 | name: "default",
49 | pattern: "{controller=Home}/{action=Index}/{id?}");
50 | });
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/Views/Home/Privacy.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Privacy Policy";
3 | }
4 | @ViewData["Title"]
5 |
6 | Use this page to detail your site's privacy policy.
7 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/Views/Shared/Error.cshtml:
--------------------------------------------------------------------------------
1 | @model ErrorViewModel
2 | @{
3 | ViewData["Title"] = "Error";
4 | }
5 |
6 | Error.
7 | An error occurred while processing your request.
8 |
9 | @if (Model.ShowRequestId)
10 | {
11 |
12 | Request ID: @Model.RequestId
13 |
14 | }
15 |
16 | Development Mode
17 |
18 | Swapping to Development environment will display more detailed information about the error that occurred.
19 |
20 |
21 | The Development environment shouldn't be enabled for deployed applications.
22 | It can result in displaying sensitive information from exceptions to end users.
23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
24 | and restarting the app.
25 |
26 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | @ViewData["Title"]
7 |
8 |
9 |
10 |
11 |
18 |
19 |
20 | @RenderBody()
21 |
22 |
23 |
24 |
29 |
30 |
31 |
32 | @RenderSection("Scripts", required: false)
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/Views/Shared/_ValidationScriptsPartial.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @using Come.AspNetCore.Sample
2 | @using Come.AspNetCore.Sample.Models
3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "_Layout";
3 | }
4 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/appsettings.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geekoutnet/CollectiveOAuth/ccab5ac92f048eb887a66ebdddd428391adb97eb/Come.AspNetCore.Sample/appsettings.json
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/74859ed3c048d2f62d27ffb52db3badc.html:
--------------------------------------------------------------------------------
1 | This file is used to verify domain ownership, please upload it to the root directory of your domain name, thank you. By Xiaomi Company
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/css/site.css:
--------------------------------------------------------------------------------
1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
2 | for details on configuring this project to bundle and minify static web assets. */
3 |
4 | a.navbar-brand {
5 | white-space: normal;
6 | text-align: center;
7 | word-break: break-all;
8 | }
9 |
10 | /* Provide sufficient contrast against white background */
11 | a {
12 | color: #0366d6;
13 | }
14 |
15 | .btn-primary {
16 | color: #fff;
17 | background-color: #1b6ec2;
18 | border-color: #1861ac;
19 | }
20 |
21 | .nav-pills .nav-link.active, .nav-pills .show > .nav-link {
22 | color: #fff;
23 | background-color: #1b6ec2;
24 | border-color: #1861ac;
25 | }
26 |
27 | /* Sticky footer styles
28 | -------------------------------------------------- */
29 | html {
30 | font-size: 14px;
31 | }
32 | @media (min-width: 768px) {
33 | html {
34 | font-size: 16px;
35 | }
36 | }
37 |
38 | .border-top {
39 | border-top: 1px solid #e5e5e5;
40 | }
41 | .border-bottom {
42 | border-bottom: 1px solid #e5e5e5;
43 | }
44 |
45 | .box-shadow {
46 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
47 | }
48 |
49 | button.accept-policy {
50 | font-size: 1rem;
51 | line-height: inherit;
52 | }
53 |
54 | /* Sticky footer styles
55 | -------------------------------------------------- */
56 | html {
57 | position: relative;
58 | min-height: 100%;
59 | }
60 |
61 | body {
62 | /* Margin bottom by footer height */
63 | margin-bottom: 60px;
64 | }
65 | .footer {
66 | position: absolute;
67 | bottom: 0;
68 | width: 100%;
69 | white-space: nowrap;
70 | line-height: 60px; /* Vertically center the text there */
71 | }
72 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geekoutnet/CollectiveOAuth/ccab5ac92f048eb887a66ebdddd428391adb97eb/Come.AspNetCore.Sample/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/js/site.js:
--------------------------------------------------------------------------------
1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
2 | // for details on configuring this project to bundle and minify static web assets.
3 |
4 | // Write your JavaScript code.
5 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/lib/bootstrap/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2011-2018 Twitter, Inc.
4 | Copyright (c) 2011-2018 The Bootstrap Authors
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
3 | * Copyright 2011-2019 The Bootstrap Authors
4 | * Copyright 2011-2019 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) .NET Foundation. All rights reserved.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | these files except in compliance with the License. You may obtain a copy of the
5 | License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software distributed
10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | specific language governing permissions and limitations under the License.
13 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js:
--------------------------------------------------------------------------------
1 | // Unobtrusive validation support library for jQuery and jQuery Validate
2 | // Copyright (c) .NET Foundation. All rights reserved.
3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
4 | // @version v3.2.11
5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a(" ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive});
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/lib/jquery-validation/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | =====================
3 |
4 | Copyright Jörn Zaefferer
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/Come.AspNetCore.Sample/wwwroot/lib/jquery/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright JS Foundation and other contributors, https://js.foundation/
2 |
3 | This software consists of voluntary contributions made by many
4 | individuals. For exact contribution history, see the revision history
5 | available at https://github.com/jquery/jquery
6 |
7 | The following license applies to all parts of this software except as
8 | documented below:
9 |
10 | ====
11 |
12 | Permission is hereby granted, free of charge, to any person obtaining
13 | a copy of this software and associated documentation files (the
14 | "Software"), to deal in the Software without restriction, including
15 | without limitation the rights to use, copy, modify, merge, publish,
16 | distribute, sublicense, and/or sell copies of the Software, and to
17 | permit persons to whom the Software is furnished to do so, subject to
18 | the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be
21 | included in all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 |
31 | ====
32 |
33 | All files located in the node_modules and external directories are
34 | externally maintained libraries used by this software which have their
35 | own licenses; we recommend you read them, as their terms may differ from
36 | the terms above.
37 |
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Cache/DefaultAuthStateCache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Come.CollectiveOAuth.Cache
4 | {
5 | public class DefaultAuthStateCache : IAuthStateCache
6 | {
7 | ///
8 | /// 默认缓存前缀
9 | ///
10 | private static string Default_Cache_Prefix = "CollectiveOAuth_Status_";
11 |
12 | public void cache(string key, string value)
13 | {
14 | HttpRuntimeCache.Set($"{Default_Cache_Prefix}{key}", value);
15 | }
16 |
17 | public void cache(string key, string value, long timeout)
18 | {
19 | HttpRuntimeCache.Set($"{Default_Cache_Prefix}{key}", value, timeout);
20 | }
21 |
22 | public bool containsKey(string key)
23 | {
24 | var cacheObj = HttpRuntimeCache.Get($"{Default_Cache_Prefix}{key}");
25 | if (cacheObj != null)
26 | {
27 | return true;
28 | }
29 |
30 | return false;
31 | }
32 |
33 | public string get(string key)
34 | {
35 | var cacheObj = HttpRuntimeCache.Get($"{Default_Cache_Prefix}{key}");
36 | if (cacheObj != null)
37 | {
38 | return Convert.ToString(cacheObj);
39 | }
40 | else
41 | {
42 | return null;
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Cache/HttpRuntimeCache.cs:
--------------------------------------------------------------------------------
1 | #if NET45
2 | using System;
3 | using System.Web;
4 |
5 | namespace Come.CollectiveOAuth.Cache
6 | {
7 | public class HttpRuntimeCache
8 | {
9 | ///
10 | /// 获取数据缓存
11 | ///
12 | /// 键
13 | public static object Get(string CacheKey)
14 | {
15 | System.Web.Caching.Cache objCache = HttpRuntime.Cache;
16 |
17 | return objCache[CacheKey];
18 | }
19 |
20 | ///
21 | /// 设置数据缓存
22 | /// 变化时间过期(平滑过期)。表示缓存连续2个小时没有访问就过期(TimeSpan.FromSeconds(7200))。
23 | ///
24 | /// 键
25 | /// 值
26 | /// 过期时间,默认7200秒
27 | /// 是否相对过期,默认是;否,则固定时间过期
28 | public static void Set(string CacheKey, object objObject, long Second = 7200, bool Sliding = true)
29 | {
30 | System.Web.Caching.Cache objCache = HttpRuntime.Cache;
31 | if (Sliding)
32 | {
33 | objCache.Insert(CacheKey, objObject, null, DateTime.MaxValue, TimeSpan.FromSeconds(Second));
34 | }
35 | else
36 | {
37 | objCache.Insert(CacheKey, objObject, null, DateTime.Now.AddSeconds(Second), TimeSpan.Zero);
38 | }
39 | }
40 |
41 | ///
42 | /// 移除指定数据缓存
43 | ///
44 | /// 键
45 | public static void Remove(string CacheKey)
46 | {
47 | System.Web.Caching.Cache objCache = HttpRuntime.Cache;
48 | objCache.Remove(CacheKey);
49 | }
50 |
51 | ///
52 | /// 移除全部缓存
53 | ///
54 | public static void RemoveAll()
55 | {
56 | var objCache = HttpRuntime.Cache.GetEnumerator();
57 | while (objCache.MoveNext())
58 | {
59 | HttpRuntime.Cache.Remove(objCache.Key.ToString());
60 | }
61 | }
62 | }
63 | }
64 | #else
65 | using Microsoft.Extensions.Caching.Memory;
66 | using System;
67 | using System.Web;
68 |
69 | namespace Come.CollectiveOAuth.Cache
70 | {
71 | public class HttpRuntimeCache
72 | {
73 | ///
74 | /// 获取数据缓存
75 | ///
76 | /// 键
77 | ///
78 | /// 缓存
79 | ///
80 | public static IMemoryCache memoryCache => new MemoryCache(new MemoryCacheOptions() { });
81 |
82 | ///
83 | /// 获取数据缓存
84 | ///
85 | /// 键
86 | public static object Get(string CacheKey)
87 | {
88 | memoryCache.TryGetValue(CacheKey, out object result);
89 | return result;
90 | }
91 |
92 | ///
93 | /// 设置数据缓存
94 | /// 变化时间过期(平滑过期)。表示缓存连续2个小时没有访问就过期(TimeSpan.FromSeconds(7200))。
95 | ///
96 | /// 键
97 | /// 值
98 | /// 过期时间,默认7200秒
99 | /// 是否相对过期,默认是;否,则固定时间过期
100 | public static void Set(string CacheKey, object objObject, long Second = 7200, bool Sliding = true) =>
101 | memoryCache.Set(CacheKey, objObject, Sliding ?
102 | new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(Second)) :
103 | new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromSeconds(Second)));
104 |
105 | ///
106 | /// 移除指定数据缓存
107 | ///
108 | /// 键
109 | public static void Remove(string CacheKey) => memoryCache.Remove(CacheKey);
110 |
111 | ///
112 | /// 移除全部缓存
113 | ///
114 | public static void RemoveAll() => memoryCache.Dispose();
115 | }
116 | }
117 | #endif
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Cache/IAuthStateCache.cs:
--------------------------------------------------------------------------------
1 | namespace Come.CollectiveOAuth.Cache
2 | {
3 | public interface IAuthStateCache
4 | {
5 | /**
6 | * 存入缓存
7 | *
8 | * @param key 缓存key
9 | * @param value 缓存内容
10 | */
11 | void cache(string key, string value);
12 |
13 | /**
14 | * 存入缓存
15 | *
16 | * @param key 缓存key
17 | * @param value 缓存内容
18 | * @param timeout 指定缓存过期时间(毫秒)
19 | */
20 | void cache(string key, string value, long timeout);
21 |
22 | /**
23 | * 获取缓存内容
24 | *
25 | * @param key 缓存key
26 | * @return 缓存内容
27 | */
28 | string get(string key);
29 |
30 | /**
31 | * 是否存在key,如果对应key的value值已过期,也返回false
32 | *
33 | * @param key 缓存key
34 | * @return true:存在key,并且value没过期;false:key不存在或者已过期
35 | */
36 | bool containsKey(string key);
37 | }
38 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Come.CollectiveOAuth.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1;netstandard2.0;net45
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Libraries\TopSdk.dll
16 |
17 |
18 |
19 |
20 |
21 | 4.2.13
22 |
23 |
24 | 3.1.1
25 |
26 |
27 | 3.1.1
28 |
29 |
30 | 4.7.0
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 4.2.13
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | 4.2.13
56 |
57 |
58 | 3.1.1
59 |
60 |
61 | 3.1.1
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/AlipayMPAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 支付宝服务窗
7 | */
8 | public class AlipayMPAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://openapi.alipay.com/gateway.do";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://openapi.alipay.com/gateway.do";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.ALIPAY_MP.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/BaiduAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 百度开放平台
7 | */
8 | public class BaiduAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://openapi.baidu.com/oauth/2.0/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://openapi.baidu.com/oauth/2.0/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://openapi.baidu.com/rest/2.0/passport/users/getInfo";
23 | }
24 |
25 | public string revoke()
26 | {
27 | return "https://openapi.baidu.com/rest/2.0/passport/auth/revokeAuthorization";
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://openapi.baidu.com/oauth/2.0/token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.BAIDU.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/CodingAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Coding扣钉
7 | */
8 | public class CodingAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://coding.net/oauth_authorize.html";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://coding.net/api/oauth/access_token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://coding.net/api/account/current_user";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.CODING.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/DingTalkScanAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 钉钉扫码
7 | */
8 | public class DingTalkScanAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://oapi.dingtalk.com/connect/qrconnect";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | throw new System.NotImplementedException(AuthResponseStatus.UNSUPPORTED.GetDesc());
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://oapi.dingtalk.com/sns/getuserinfo_bycode"; ;
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.DINGTALK_SCAN.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/DouYinAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 抖音
7 | */
8 | public class DouyinAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://open.douyin.com/platform/oauth/connect";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://open.douyin.com/oauth/access_token/";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://open.douyin.com/oauth/userinfo/";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://open.douyin.com/oauth/refresh_token/";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.DOUYIN.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/ElemeAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 饿了么
7 | */
8 | public class ElemeAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://open-api.shop.ele.me/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://open-api.shop.ele.me/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://open-api.shop.ele.me/api/v1/";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://open-api.shop.ele.me/token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.ELEME.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/FackbookAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Facebook
7 | */
8 | public class FackbookAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://www.facebook.com/v3.3/dialog/oauth";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://graph.facebook.com/v3.3/oauth/access_token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://graph.facebook.com/v3.3/me";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.FACEBOOK.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/GiteeAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Gitee
7 | */
8 | public class GiteeAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://gitee.com/oauth/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://gitee.com/oauth/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://gitee.com/api/v5/user";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.GITEE.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/GithubAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Github
7 | */
8 | public class GithubAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://github.com/login/oauth/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://github.com/login/oauth/access_token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.github.com/user";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.GITHUB.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/GitlabAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Gitlab
7 | */
8 | public class GitlabAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://gitlab.com/oauth/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://gitlab.com/oauth/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://gitlab.com/api/v4/user";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.GITLAB.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/GoogleAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Google(谷歌)
7 | */
8 | public class GoogleAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://accounts.google.com/o/oauth2/v2/auth";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://www.googleapis.com/oauth2/v4/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://www.googleapis.com/oauth2/v3/userinfo";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.GOOGLE.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/HuaweiAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 华为
7 | */
8 | public class HuaweiAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://oauth-login.cloud.huawei.com/oauth2/v2/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.vmall.com/rest.php";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://oauth.kujiale.com/oauth2/auth/token/refresh";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.KUJIALE.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/KujialeAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 酷家乐
7 | */
8 | public class KujialeAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://oauth.kujiale.com/oauth2/show";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://oauth.kujiale.com/oauth2/auth/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://oauth.kujiale.com/oauth2/openapi/user";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.KUJIALE.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/LinkedInAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Linkin领英
7 | */
8 | public class LinkedInAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://www.linkedin.com/oauth/v2/authorization";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://www.linkedin.com/oauth/v2/accessToken";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.linkedin.com/v2/me";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://www.linkedin.com/oauth/v2/accessToken";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.LINKEDIN.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/MeituanAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 美团
7 | */
8 | public class MeituanAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://openapi.waimai.meituan.com/oauth/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://openapi.waimai.meituan.com/oauth/access_token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://openapi.waimai.meituan.com/oauth/userinfo";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://openapi.waimai.meituan.com/oauth/refresh_token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.MEITUAN.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/MicrosoftAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 微软
7 | */
8 | public class MicrosoftAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://graph.microsoft.com/v1.0/me";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.MICROSOFT.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/OschinaAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * OSChina开源中国
7 | */
8 | public class OschinaAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://www.oschina.net/action/oauth2/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://www.oschina.net/action/openapi/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://www.oschina.net/action/openapi/user";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.OSCHINA.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/PinterestAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Pinterest
7 | */
8 | public class PinterestAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://api.pinterest.com/oauth";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://api.pinterest.com/v1/oauth/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.pinterest.com/v1/me";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.PINTEREST.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/QQAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 腾讯QQ
7 | */
8 | public class QQAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://graph.qq.com/oauth2.0/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://graph.qq.com/oauth2.0/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://graph.qq.com/user/get_user_info";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://graph.qq.com/oauth2.0/token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.QQ.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/RenrenAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 人人网
7 | */
8 | public class RenrenAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://graph.renren.com/oauth/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://graph.renren.com/oauth/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.renren.com/v2/user/get";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://graph.renren.com/oauth/token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.RENREN.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/StackOverflowAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Stack Overflow
7 | */
8 | public class StackOverflowAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://stackoverflow.com/oauth";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://stackoverflow.com/oauth/access_token/json";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.stackexchange.com/2.2/me";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.STACK_OVERFLOW.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/TaobaoAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 淘宝
7 | */
8 | public class TaobaoAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://oauth.taobao.com/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://oauth.taobao.com/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | throw new System.NotImplementedException();
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.TAOBAO.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/TeambitionAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Teambition
7 | */
8 | public class TeambitionAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://account.teambition.com/oauth2/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://account.teambition.com/oauth2/access_token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.teambition.com/users/me";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://account.teambition.com/oauth2/refresh_token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.TEAMBITION.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/ToutiaoAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 今日头条
7 | */
8 | public class ToutiaoAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://open.snssdk.com/auth/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://open.snssdk.com/auth/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://open.snssdk.com/data/user_profile";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.TOUTIAO.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/TwitterAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * Twitter
7 | */
8 | public class TwitterAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://api.twitter.com/oauth/authenticate";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://api.twitter.com/oauth/access_token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.twitter.com/1.1/users/show.json";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.TWITTER.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/WechatEnterpriseAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 企业微信
7 | */
8 | public class WechatEnterpriseAuthSource : IAuthSource
9 | {
10 |
11 | public string accessToken()
12 | {
13 | return "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
14 | }
15 |
16 | public string authorize()
17 | {
18 | //return "https://open.work.weixin.qq.com/wwopen/sso/qrConnect";
19 | return "https://open.weixin.qq.com/connect/oauth2/authorize";
20 | }
21 |
22 | public string getName()
23 | {
24 | return DefaultAuthSourceEnum.WECHAT_ENTERPRISE.ToString();
25 | }
26 |
27 | public string refresh()
28 | {
29 | throw new System.NotImplementedException();
30 | }
31 |
32 | public string revoke()
33 | {
34 | throw new System.NotImplementedException();
35 | }
36 |
37 | public string userInfo()
38 | {
39 | return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/WechatEnterpriseScanAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 企业微信扫码
7 | */
8 | public class WechatEnterpriseScanAuthSource : IAuthSource
9 | {
10 |
11 | public string accessToken()
12 | {
13 | return "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
14 | }
15 |
16 | public string authorize()
17 | {
18 | return "https://open.work.weixin.qq.com/wwopen/sso/qrConnect";
19 | }
20 |
21 | public string getName()
22 | {
23 | return DefaultAuthSourceEnum.WECHAT_ENTERPRISE_SCAN.ToString();
24 | }
25 |
26 | public string refresh()
27 | {
28 | throw new System.NotImplementedException();
29 | }
30 |
31 | public string revoke()
32 | {
33 | throw new System.NotImplementedException();
34 | }
35 |
36 | public string userInfo()
37 | {
38 | return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/WechatMPAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 微信公众平台
7 | */
8 | public class WechatMPAuthSource : IAuthSource
9 | {
10 | public string accessToken()
11 | {
12 | return "https://api.weixin.qq.com/sns/oauth2/access_token";
13 | }
14 |
15 | public string authorize()
16 | {
17 | return "https://open.weixin.qq.com/connect/oauth2/authorize";
18 | }
19 |
20 | public string getName()
21 | {
22 | return DefaultAuthSourceEnum.WECHAT_MP.ToString();
23 | }
24 |
25 | public string refresh()
26 | {
27 | return "https://api.weixin.qq.com/sns/oauth2/refresh_token";
28 | }
29 |
30 | public string revoke()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string userInfo()
36 | {
37 | return "https://api.weixin.qq.com/sns/userinfo";
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/WechatOpenAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 微信开放平台
7 | */
8 | public class WechatOpenAuthSource : IAuthSource
9 | {
10 | public string accessToken()
11 | {
12 | return "https://api.weixin.qq.com/sns/oauth2/access_token";
13 | }
14 |
15 | public string authorize()
16 | {
17 | return "https://open.weixin.qq.com/connect/qrconnect";
18 | }
19 |
20 | public string getName()
21 | {
22 | return DefaultAuthSourceEnum.WECHAT_OPEN.ToString();
23 | }
24 |
25 | public string refresh()
26 | {
27 | return "https://api.weixin.qq.com/sns/oauth2/refresh_token";
28 | }
29 |
30 | public string revoke()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string userInfo()
36 | {
37 | return "https://api.weixin.qq.com/sns/userinfo";
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/WeiboAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 微博
7 | */
8 | public class WeiboAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://api.weibo.com/oauth2/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://api.weibo.com/oauth2/access_token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://api.weibo.com/2/users/show.json";
23 | }
24 |
25 | public string revoke()
26 | {
27 | return "https://api.weibo.com/oauth2/revokeoauth2";
28 | }
29 |
30 | public string refresh()
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.WEIBO.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/AuthSources/XiaoMiAuthSource.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Config
4 | {
5 | /**
6 | * 小米开放平台
7 | */
8 | public class XiaoMiAuthSource : IAuthSource
9 | {
10 | public string authorize()
11 | {
12 | return "https://account.xiaomi.com/oauth2/authorize";
13 | }
14 |
15 | public string accessToken()
16 | {
17 | return "https://account.xiaomi.com/oauth2/token";
18 | }
19 |
20 | public string userInfo()
21 | {
22 | return "https://open.account.xiaomi.com/user/profile";
23 | }
24 |
25 | public string revoke()
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public string refresh()
31 | {
32 | return "https://account.xiaomi.com/oauth2/token";
33 | }
34 |
35 | public string getName()
36 | {
37 | return DefaultAuthSourceEnum.XIAOMI.ToString();
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/ClientConfig.cs:
--------------------------------------------------------------------------------
1 | namespace Come.CollectiveOAuth.Config
2 | {
3 | /**
4 | * CollectiveOAuth配置类
5 | *
6 | * @author wei.fu (wei.fu@rthinkingsoft.cn)
7 | * @since 1.8
8 | */
9 | public class ClientConfig
10 | {
11 | /**
12 | * 客户端id:对应各平台的appKey
13 | */
14 | public string clientId { get; set; }
15 |
16 | /**
17 | * 客户端Secret:对应各平台的appSecret
18 | */
19 | public string clientSecret { get; set; }
20 |
21 | /**
22 | * 登录成功后的回调地址
23 | */
24 | public string redirectUri { get; set; }
25 |
26 | /**
27 | * 支付宝公钥:当选择支付宝登录时,该值可用
28 | * 对应“RSA2(SHA256)密钥”中的“支付宝公钥”
29 | */
30 | public string alipayPublicKey { get; set; }
31 |
32 | /**
33 | * 是否需要申请unionid,目前只针对qq登录
34 | * 注:qq授权登录时,获取unionid需要单独发送邮件申请权限。如果个人开发者账号中申请了该权限,可以将该值置为true,在获取openId时就会同步获取unionId
35 | * 参考链接:http://wiki.connect.qq.com/unionid%E4%BB%8B%E7%BB%8D
36 | *
37 | * 1.7.1版本新增参数
38 | */
39 | public string unionId { get; set; }
40 |
41 | /**
42 | * Stack Overflow Key
43 | *
44 | *
45 | * @since 1.9.0
46 | */
47 | public string stackOverflowKey { get; set; }
48 |
49 | /**
50 | * 企业微信,授权方的网页应用ID
51 | *
52 | * @since 1.10.0
53 | */
54 | public string agentId { get; set; }
55 |
56 | /**
57 | * 企业微信,授权方的网页应用ID
58 | *
59 | * @since 1.10.0
60 | */
61 | public string scope { get; set; }
62 | }
63 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/DefaultAuthSourceEnum.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace Come.CollectiveOAuth.Enums
4 | {
5 | public enum DefaultAuthSourceEnum
6 | {
7 | [Description("微信公众平台")]
8 | WECHAT_MP,
9 |
10 | [Description("微信开放平台")]
11 | WECHAT_OPEN,
12 |
13 | [Description("企业微信自动授权")]
14 | WECHAT_ENTERPRISE,
15 |
16 | [Description("企业微信扫码")]
17 | WECHAT_ENTERPRISE_SCAN,
18 |
19 | [Description("支付宝服务窗")]
20 | ALIPAY_MP,
21 |
22 | [Description("码云授权")]
23 | GITEE,
24 |
25 | [Description("Github授权")]
26 | GITHUB,
27 |
28 | [Description("百度开放平台")]
29 | BAIDU,
30 |
31 | [Description("小米开放平台")]
32 | XIAOMI,
33 |
34 | [Description("钉钉扫码")]
35 | DINGTALK_SCAN,
36 |
37 | [Description("OSChina开源中国")]
38 | OSCHINA,
39 |
40 | [Description("Coding扣钉")]
41 | CODING,
42 |
43 | [Description("LinkedIn领英")]
44 | LINKEDIN,
45 |
46 | [Description("微博")]
47 | WEIBO,
48 |
49 | [Description("腾讯QQ")]
50 | QQ,
51 |
52 | [Description("抖音")]
53 | DOUYIN,
54 |
55 | [Description("Google(谷歌)")]
56 | GOOGLE,
57 |
58 | [Description("Facebook")]
59 | FACEBOOK,
60 |
61 | [Description("微软")]
62 | MICROSOFT,
63 |
64 | [Description("今日头条")]
65 | TOUTIAO,
66 |
67 | [Description("Teambition")]
68 | TEAMBITION,
69 |
70 | [Description("人人网")]
71 | RENREN,
72 |
73 | [Description("Pinterest")]
74 | PINTEREST,
75 |
76 | [Description("Stack Overflow")]
77 | STACK_OVERFLOW,
78 |
79 | [Description("华为")]
80 | HUAWEI,
81 |
82 | [Description("酷家乐")]
83 | KUJIALE,
84 |
85 | [Description("Gitlab")]
86 | GITLAB,
87 |
88 | [Description("美团")]
89 | MEITUAN,
90 |
91 | [Description("饿了么")]
92 | ELEME,
93 |
94 | [Description("Twitter")]
95 | TWITTER,
96 |
97 | [Description("淘宝")]
98 | TAOBAO,
99 |
100 | }
101 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Config/IAuthSource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | /**
4 | * OAuth平台的API地址的统一接口,提供以下方法:
5 | * 1) {@link AuthSource#authorize()}: 获取授权url. 必须实现
6 | * 2) {@link AuthSource#accessToken()}: 获取accessToken的url. 必须实现
7 | * 3) {@link AuthSource#userInfo()}: 获取用户信息的url. 必须实现
8 | * 4) {@link AuthSource#revoke()}: 获取取消授权的url. 非必须实现接口(部分平台不支持)
9 | * 5) {@link AuthSource#refresh()}: 获取刷新授权的url. 非必须实现接口(部分平台不支持)
10 | *
11 | * 注:
12 | * ①、如需通过JustAuth扩展实现第三方授权,请参考{@link AuthDefaultSource}自行创建对应的枚举类并实现{@link AuthSource}接口
13 | * ②、如果不是使用的枚举类,那么在授权成功后获取用户信息时,需要单独处理source字段的赋值
14 | * ③、如果扩展了对应枚举类时,在{@link me.zhyd.oauth.request.AuthRequest#login(AuthCallback)}中可以通过{@code xx.toString()}获取对应的source
15 | *
16 | * @author wei.fu (wei.fu@rthinkingsoft.cn)
17 | * @version 1.0
18 | * @since 1.12.0
19 | */
20 |
21 | namespace Come.CollectiveOAuth.Config
22 | {
23 | public interface IAuthSource
24 | {
25 | /**
26 | * 授权的api
27 | *
28 | * @return url
29 | */
30 | string authorize();
31 |
32 | /**
33 | * 获取accessToken的api
34 | *
35 | * @return url
36 | */
37 | string accessToken();
38 |
39 | /**
40 | * 获取用户信息的api
41 | *
42 | * @return url
43 | */
44 | string userInfo();
45 |
46 | /**
47 | * 取消授权的api
48 | *
49 | * @return url
50 | */
51 | string revoke();
52 |
53 |
54 | /**
55 | * 刷新授权的api
56 | *
57 | * @return url
58 | */
59 | string refresh();
60 |
61 | /**
62 | * 获取Source的字符串名字
63 | *
64 | * @return name
65 | */
66 | string getName();
67 | }
68 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Enums/AuthResponseStatus.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace Come.CollectiveOAuth.Enums
4 | {
5 | public enum AuthResponseStatus
6 | {
7 | /**
8 | * 2000:正常;
9 | * other:调用异常,具体异常内容见{@code msg}
10 | */
11 | [Description("Success")]
12 | SUCCESS = 2000,
13 |
14 | [Description("Failure")]
15 | FAILURE = 5000,
16 |
17 | [Description("Not Implemented")]
18 | NOT_IMPLEMENTED = 5001,
19 |
20 | [Description("Parameter incomplete")]
21 | PARAMETER_INCOMPLETE = 5002,
22 |
23 | [Description("Unsupported operation")]
24 | UNSUPPORTED = 5003,
25 |
26 | [Description("AuthDefaultSource cannot be null")]
27 | NO_AUTH_SOURCE = 5004,
28 |
29 | [Description("Unidentified platform")]
30 | UNIDENTIFIED_PLATFORM = 5005,
31 |
32 | [Description("Illegal redirect uri")]
33 | ILLEGAL_REDIRECT_URI = 5006,
34 |
35 | [Description("Illegal request")]
36 | ILLEGAL_REQUEST = 5007,
37 |
38 | [Description("Illegal code")]
39 | ILLEGAL_CODE = 5008,
40 |
41 | [Description("Illegal state")]
42 | ILLEGAL_STATUS = 5009,
43 |
44 | [Description("The refresh token is required; it must not be null")]
45 | REQUIRED_REFRESH_TOKEN = 5010,
46 | }
47 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Enums/AuthToutiaoErrorCode.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace Come.CollectiveOAuth.Enums
4 | {
5 | /**
6 | * 今日头条授权登录时的异常状态码
7 | *
8 | * @author wei.fu (wei.fu@rthinkingsoft.cn)
9 | * @since 1.8
10 | */
11 | public enum AuthToutiaoErrorCode
12 | {
13 | /**
14 | * 0:正常;
15 | * other:调用异常,具体异常内容见{@code desc}
16 | */
17 | [Description("接口调用成功")]
18 | EC0 = 0,
19 |
20 | [Description("API配置错误,未传入Client Key")]
21 | EC1 = 1,
22 |
23 | [Description("API配置错误,Client Key错误,请检查是否和开放平台的ClientKey一致")]
24 | EC2 = 2,
25 |
26 | [Description("没有授权信息")]
27 | EC3 = 3,
28 |
29 | [Description("响应类型错误")]
30 | EC4 = 4,
31 |
32 | [Description("授权类型错误")]
33 | EC5 = 5,
34 |
35 | [Description("client_secret错误")]
36 | EC6 = 6,
37 |
38 | [Description("authorize_code过期")]
39 | EC7 = 7,
40 |
41 | [Description("指定url的scheme不是https")]
42 | EC8 = 8,
43 |
44 | [Description("接口内部错误,请联系头条技术")]
45 | EC9 = 9,
46 |
47 | [Description("access_token过期")]
48 | EC10 = 10,
49 |
50 | [Description("缺少access_token")]
51 | EC11 = 11,
52 |
53 | [Description("参数缺失")]
54 | EC12 = 12,
55 |
56 | [Description("url错误")]
57 | EC13 = 13,
58 |
59 | [Description("域名与登记域名不匹配")]
60 | EC21 = 21,
61 |
62 | [Description("未知错误,请联系头条技术")]
63 | EC999 = 999,
64 | }
65 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Enums/AuthUserGender.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace Come.CollectiveOAuth.Enums
4 | {
5 | public enum AuthUserGender
6 | {
7 | [Description("男")]
8 | MALE=1,
9 | [Description("女")]
10 | FEMALE = 0,
11 | [Description("未知")]
12 | UNKNOWN = -1
13 | }
14 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Enums/EnumHelper/EnumModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Come.CollectiveOAuth.Enums
4 | {
5 | public struct EnumModel
6 | {
7 | public EnumModel(Enum um)
8 | {
9 | this.value = (int)Convert.ChangeType(um, typeof(int));
10 | this.name = um.ToString();
11 | this.text = um.GetDesc();
12 | }
13 | public int value { get; set; }
14 | public string name { get; set; }
15 | public string text { get; set; }
16 | }
17 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Enums/EnumHelper/EnumObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Come.CollectiveOAuth.Enums
4 | {
5 | public struct EnumObject
6 | {
7 | public EnumObject(Enum um, string picture = null)
8 | {
9 | this.ID = (int)Convert.ChangeType(um, typeof(int));
10 | this.Name = um.ToString();
11 | this.Description = um.GetDesc();
12 | this.Picture = picture;
13 | }
14 |
15 | public EnumObject(int id, string name)
16 | {
17 | this.ID = id;
18 | this.Name = this.Description = name;
19 | this.Picture = null;
20 | }
21 |
22 | public EnumObject(int id, string name, string description, string picture)
23 | {
24 | this.ID = id;
25 | this.Name = name;
26 | this.Description = description;
27 | this.Picture = picture;
28 | }
29 |
30 | public int ID;
31 |
32 | public string Name;
33 |
34 | public string Description;
35 |
36 | public string Picture;
37 | }
38 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Libraries/TopSdk.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geekoutnet/CollectiveOAuth/ccab5ac92f048eb887a66ebdddd428391adb97eb/Come.CollectiveOAuth/Libraries/TopSdk.dll
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Models/AuthCallback.cs:
--------------------------------------------------------------------------------
1 | namespace Come.CollectiveOAuth.Models
2 | {
3 | public class AuthCallback
4 | {
5 | /**
6 | * 访问AuthorizeUrl后回调时带的参数code
7 | */
8 | public string code { get; set; }
9 |
10 | /**
11 | * 访问AuthorizeUrl后回调时带的参数auth_code,该参数目前只使用于支付宝登录
12 | */
13 | public string auth_code { get; set; }
14 |
15 | /**
16 | * 访问AuthorizeUrl后回调时带的参数state,用于和请求AuthorizeUrl前的state比较,防止CSRF攻击
17 | */
18 | public string state { get; set; }
19 |
20 | /**
21 | * 华为授权登录接受code的参数名
22 | *
23 | * @since 1.10.0
24 | */
25 | public string authorization_code { get; set; }
26 |
27 | /**
28 | * Twitter回调后返回的oauth_token
29 | *
30 | * @since 1.13.0
31 | */
32 | public string oauthToken { get; set; }
33 |
34 | /**
35 | * Twitter回调后返回的oauth_verifier
36 | *
37 | * @since 1.13.0
38 | */
39 | public string oauthVerifier { get; set; }
40 | }
41 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Models/AuthResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Come.CollectiveOAuth.Enums;
3 |
4 | namespace Come.CollectiveOAuth.Models
5 | {
6 | public class AuthResponse
7 | {
8 | /**
9 | * 授权响应状态码
10 | */
11 | public int code { get; set; }
12 |
13 | /**
14 | * 授权响应信息
15 | */
16 | public string msg { get; set; }
17 |
18 | /**
19 | * 授权响应数据,当且仅当 code = 2000 时返回
20 | */
21 | public object data { get; set; }
22 |
23 | /**
24 | * 是否请求成功
25 | *
26 | * @return true or false
27 | */
28 | public bool ok()
29 | {
30 | return this.code == Convert.ToInt32(AuthResponseStatus.SUCCESS);
31 | }
32 |
33 | public AuthResponse(int code, string msg, object data = null)
34 | {
35 | this.code = code;
36 | this.msg = msg;
37 | this.data = data;
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Models/AuthToken.cs:
--------------------------------------------------------------------------------
1 | namespace Come.CollectiveOAuth.Models
2 | {
3 | /**
4 | * 授权所需的token
5 | * @author wei.fu
6 | * @since 1.8
7 | */
8 | public class AuthToken
9 | {
10 | public string accessToken { get; set; }
11 | public int expireIn { get; set; }
12 | public string refreshToken { get; set; }
13 | public string uid { get; set; }
14 | public string openId { get; set; }
15 | public string accessCode { get; set; }
16 | public string unionId { get; set; }
17 |
18 | /**
19 | * Google附带属性
20 | */
21 | public string scope { get; set; }
22 | public string tokenType { get; set; }
23 | public string idToken { get; set; }
24 |
25 | /**
26 | * 小米附带属性
27 | */
28 | public string macAlgorithm { get; set; }
29 | public string macKey { get; set; }
30 |
31 | /**
32 | * 企业微信附带属性
33 | *
34 | * @since 1.10.0
35 | */
36 | public string code { get; set; }
37 |
38 | /**
39 | * Twitter附带属性
40 | *
41 | * @since 1.13.0
42 | */
43 | public string oauthToken { get; set; }
44 | public string oauthTokenSecret { get; set; }
45 | public string userId { get; set; }
46 | public string screenName { get; set; }
47 | public bool oauthCallbackConfirmed { get; set; }
48 |
49 | }
50 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Models/AuthUser.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Enums;
2 |
3 | namespace Come.CollectiveOAuth.Models
4 | {
5 | public class AuthUser
6 | {
7 | /**
8 | * 用户第三方系统的唯一id。在调用方集成改组件时,可以用uuid + source唯一确定一个用户
9 | *
10 | * @since 1.3.3
11 | */
12 | public string uuid { get; set; }
13 | /**
14 | * 用户名
15 | */
16 | public string username { get; set; }
17 | /**
18 | * 用户昵称
19 | */
20 | public string nickname { get; set; }
21 | /**
22 | * 用户头像
23 | */
24 | public string avatar { get; set; }
25 | /**
26 | * 用户网址
27 | */
28 | public string blog { get; set; }
29 | /**
30 | * 所在公司
31 | */
32 | public string company { get; set; }
33 | /**
34 | * 位置
35 | */
36 | public string location { get; set; }
37 | /**
38 | * 用户邮箱
39 | */
40 | public string email { get; set; }
41 | /**
42 | * 用户备注(各平台中的用户个人介绍)
43 | */
44 | public string remark { get; set; }
45 | /**
46 | * 性别
47 | */
48 | public AuthUserGender gender { get; set; }
49 | /**
50 | * 用户来源
51 | */
52 | public string source { get; set; }
53 | /**
54 | * 用户授权的token信息
55 | */
56 | public AuthToken token { get; set; }
57 |
58 | ///
59 | /// 原有的用户信息(第三方返回的)
60 | ///
61 | public object originalUser { get; set; }
62 |
63 | public string originalUserStr { get; set; }
64 | }
65 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/AlipayMpAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Config;
2 | using Come.CollectiveOAuth.Models;
3 | using Come.CollectiveOAuth.Utils;
4 | using System;
5 | using System.Collections.Generic;
6 | using Come.CollectiveOAuth.Enums;
7 | using Come.CollectiveOAuth.Cache;
8 | using Aop.Api;
9 | using Aop.Api.Request;
10 | using Aop.Api.Response;
11 | using Newtonsoft.Json;
12 |
13 | namespace Come.CollectiveOAuth.Request
14 | {
15 | public partial class AlipayMpAuthRequest : DefaultAuthRequest
16 | {
17 | private IAopClient aopClient;
18 | public AlipayMpAuthRequest(ClientConfig config) : base(config, new AlipayMPAuthSource())
19 | {
20 | aopClient = new DefaultAopClient(source.accessToken(), config.clientId, config.clientSecret, "json", "1.0", "RSA2", config.alipayPublicKey, "GBK", false);
21 | }
22 |
23 | public AlipayMpAuthRequest(ClientConfig config, IAuthStateCache authStateCache) : base(config, new AlipayMPAuthSource(), authStateCache)
24 | {
25 | aopClient = new DefaultAopClient(source.accessToken(), config.clientId, config.clientSecret, "json", "1.0", "RSA2", config.alipayPublicKey, "GBK", false);
26 | }
27 |
28 | /**
29 | * 微信的特殊性,此时返回的信息同时包含 openid 和 access_token
30 | *
31 | * @param authCallback 回调返回的参数
32 | * @return 所有信息
33 | */
34 | protected override AuthToken getAccessToken(AuthCallback authCallback)
35 | {
36 | AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
37 | request.GrantType = "authorization_code";
38 | request.Code = authCallback.auth_code;
39 | AlipaySystemOauthTokenResponse response = null;
40 | try
41 | {
42 | response = this.aopClient.Execute(request);
43 | }
44 | catch (Exception e)
45 | {
46 | throw new Exception(e.Message);
47 | }
48 | if (response.IsError)
49 | {
50 | throw new Exception(response.SubMsg);
51 | }
52 |
53 | var authToken = new AuthToken();
54 | authToken.accessToken = response.AccessToken;
55 | authToken.uid = response.UserId;
56 | authToken.expireIn = Convert.ToInt32(response.ExpiresIn);
57 | authToken.refreshToken = response.RefreshToken;
58 | authToken.userId = response.AlipayUserId;
59 |
60 | return authToken;
61 | }
62 |
63 | protected override AuthUser getUserInfo(AuthToken authToken)
64 | {
65 | string accessToken = authToken.accessToken;
66 | AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
67 | AlipayUserInfoShareResponse response = null;
68 | try
69 | {
70 | response = this.aopClient.Execute(request, accessToken);
71 | }
72 | catch (Exception e)
73 | {
74 | throw new Exception(e.Message, e);
75 | }
76 | if (response.IsError)
77 | {
78 | throw new Exception(response.SubMsg);
79 | }
80 |
81 | string province = response.Province, city = response.City;
82 | string location = string.Format("{0} {1}", !province.IsNullOrWhiteSpace() ? "" : province, !city.IsNullOrWhiteSpace() ? "" : city);
83 |
84 | var authUser = new AuthUser();
85 | authUser.username = response.UserName.IsNullOrWhiteSpace() ? response.NickName : response.UserName;
86 | authUser.nickname = response.NickName;
87 | authUser.avatar = response.Avatar;
88 | authUser.location = location;
89 | authUser.uuid = response.UserId;
90 | authUser.gender = GlobalAuthUtil.getRealGender(response.Gender);
91 | authUser.token = authToken;
92 | authUser.source = source.getName();
93 | authUser.originalUser = response;
94 | authUser.originalUserStr = JsonConvert.SerializeObject(response);
95 | return authUser;
96 | }
97 |
98 | /**
99 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
100 | *
101 | * @param state state 验证授权流程的参数,可以防止csrf
102 | * @return 返回授权地址
103 | * @since 1.9.3
104 | */
105 | public override string authorize(string state)
106 | {
107 | return UrlBuilder.fromBaseUrl(source.authorize())
108 | .queryParam("app_id", config.clientId)
109 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "auth_user" : config.scope)
110 | .queryParam("redirect_uri", config.redirectUri)
111 | .queryParam("state", getRealState(state))
112 | .build();
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/BaiduAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Enums;
4 | using Come.CollectiveOAuth.Models;
5 | using Come.CollectiveOAuth.Utils;
6 | using System;
7 | using System.Collections.Generic;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class BaiduAuthRequest : DefaultAuthRequest
12 | {
13 | public BaiduAuthRequest(ClientConfig config) : base(config, new BaiduAuthSource())
14 | {
15 | }
16 |
17 | public BaiduAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new BaiduAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | string response = doPostAuthorizationCode(authCallback.code);
25 | var accessTokenObject = response.parseObject();
26 | this.checkResponse(accessTokenObject);
27 |
28 | var authToken = new AuthToken();
29 | authToken.accessToken = accessTokenObject.getString("access_token");
30 | authToken.refreshToken = accessTokenObject.getString("refresh_token");
31 | authToken.expireIn = accessTokenObject.getInt32("expires_in");
32 | authToken.scope = accessTokenObject.getString("scope");
33 |
34 | return authToken;
35 | }
36 |
37 | protected override AuthUser getUserInfo(AuthToken authToken)
38 | {
39 | string response = doGetUserInfo(authToken);
40 | var userObj = response.parseObject();
41 | this.checkResponse(userObj);
42 |
43 | var authUser = new AuthUser();
44 | authUser.uuid = userObj.getString("userid");
45 | authUser.username = userObj.getString("username");
46 | authUser.nickname = userObj.getString("username");
47 |
48 | string protrait = userObj.getString("portrait");
49 | authUser.avatar = protrait.IsNullOrWhiteSpace() ? null : string.Format("http://himg.bdimg.com/sys/portrait/item/{0}.jpg", protrait);
50 |
51 | authUser.remark = userObj.getString("userdetail");
52 | authUser.gender = GlobalAuthUtil.getRealGender(userObj.getString("sex"));
53 |
54 | authUser.token = authToken;
55 | authUser.source = source.getName();
56 | authUser.originalUser = userObj;
57 | authUser.originalUserStr = response;
58 | return authUser;
59 | }
60 |
61 | public override AuthResponse revoke(AuthToken authToken)
62 | {
63 | string response = doGetRevoke(authToken);
64 | var revokeObj = response.parseObject();
65 | this.checkResponse(revokeObj);
66 | // 返回1表示取消授权成功,否则失败
67 | AuthResponseStatus status = revokeObj.getInt32("result") == 1 ? AuthResponseStatus.SUCCESS : AuthResponseStatus.FAILURE;
68 | return new AuthResponse(status.GetCode(), status.GetDesc());
69 | }
70 |
71 | public override AuthResponse refresh(AuthToken authToken)
72 | {
73 | string refreshUrl = UrlBuilder.fromBaseUrl(this.source.refresh())
74 | .queryParam("grant_type", "refresh_token")
75 | .queryParam("refresh_token", authToken.refreshToken)
76 | .queryParam("client_id", this.config.clientId)
77 | .queryParam("client_secret", this.config.clientSecret)
78 | .build();
79 | string response = HttpUtils.RequestGet(refreshUrl);
80 | var accessTokenObject = response.parseObject();
81 | this.checkResponse(accessTokenObject);
82 |
83 | var newAuthToken = new AuthToken();
84 | newAuthToken.accessToken = accessTokenObject.getString("access_token");
85 | newAuthToken.refreshToken = accessTokenObject.getString("refresh_token");
86 | newAuthToken.expireIn = accessTokenObject.getInt32("expires_in");
87 | newAuthToken.scope = accessTokenObject.getString("scope");
88 |
89 | return new AuthResponse(AuthResponseStatus.SUCCESS.GetCode(), AuthResponseStatus.SUCCESS.GetDesc(), newAuthToken);
90 | }
91 |
92 | /**
93 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
94 | *
95 | * @param state state 验证授权流程的参数,可以防止csrf
96 | * @return 返回授权地址
97 | * @since 1.9.3
98 | */
99 | public override string authorize(string state)
100 | {
101 | return UrlBuilder.fromBaseUrl(source.authorize())
102 | .queryParam("response_type", "code")
103 | .queryParam("client_id", config.clientId)
104 | .queryParam("redirect_uri", config.redirectUri)
105 | .queryParam("display", "page")
106 | .queryParam("scope", "basic")
107 | .queryParam("state", getRealState(state))
108 | .build();
109 | }
110 |
111 | /**
112 | * 校验请求结果
113 | *
114 | * @param response 请求结果
115 | * @return 如果请求结果正常,则返回JSONObject
116 | */
117 | private void checkResponse(Dictionary dic)
118 | {
119 | if (dic.ContainsKey("error") || dic.ContainsKey("error_code"))
120 | {
121 | throw new Exception($@"error_code: {dic.getString("error_code")}," +
122 | $" error_description: {dic.getString("error_description")}," +
123 | $" error_msg: {dic.getString("error_msg")}");
124 | }
125 | }
126 | }
127 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/CodingAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Net;
8 | using Come.CollectiveOAuth.Enums;
9 |
10 | namespace Come.CollectiveOAuth.Request
11 | {
12 | public class CodingAuthRequest : DefaultAuthRequest
13 | {
14 | public CodingAuthRequest(ClientConfig config) : base(config, new CodingAuthSource())
15 | {
16 | }
17 |
18 | public CodingAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
19 | : base(config, new CodingAuthSource(), authStateCache)
20 | {
21 | }
22 |
23 | protected override AuthToken getAccessToken(AuthCallback authCallback)
24 | {
25 | string response = doGetAuthorizationCode(authCallback.code);
26 | var accessTokenObject = response.parseObject();
27 | this.checkResponse(accessTokenObject);
28 |
29 | var authToken = new AuthToken();
30 | authToken.accessToken = accessTokenObject.getString("access_token");
31 | authToken.expireIn = accessTokenObject.getInt32("expires_in");
32 | authToken.refreshToken = accessTokenObject.getString("refresh_token");
33 | return authToken;
34 | }
35 |
36 | protected override AuthUser getUserInfo(AuthToken authToken)
37 | {
38 | string response = doGetUserInfo(authToken);
39 | var resData = response.parseObject();
40 | this.checkResponse(resData);
41 |
42 | var userObj = resData.getString("data").parseObject();
43 |
44 | var authUser = new AuthUser();
45 | authUser.uuid = userObj.getString("id");
46 | authUser.username = userObj.getString("name");
47 | authUser.nickname = userObj.getString("name");
48 | authUser.avatar = $"{"https://coding.net/"}{userObj.getString("avatar")}";
49 | authUser.blog = $"{"https://coding.net/"}{userObj.getString("path")}";
50 | authUser.company = userObj.getString("company");
51 | authUser.location = userObj.getString("location");
52 | authUser.email = userObj.getString("email");
53 | authUser.remark = userObj.getString("slogan");
54 | authUser.gender = GlobalAuthUtil.getRealGender(userObj.getString("sex"));
55 |
56 | authUser.token = authToken;
57 | authUser.source = source.getName();
58 | authUser.originalUser = resData;
59 | authUser.originalUserStr = response;
60 | return authUser;
61 | }
62 |
63 | protected override string doGetUserInfo(AuthToken authToken)
64 | {
65 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
66 | return HttpUtils.RequestJsonGet(userInfoUrl(authToken));
67 | }
68 |
69 | protected override string doGetAuthorizationCode(String code)
70 | {
71 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
72 | return HttpUtils.RequestJsonGet(accessTokenUrl(code));
73 | }
74 |
75 | /**
76 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
77 | *
78 | * @param state state 验证授权流程的参数,可以防止csrf
79 | * @return 返回授权地址
80 | * @since 1.9.3
81 | */
82 | public override string authorize(string state)
83 | {
84 | return UrlBuilder.fromBaseUrl(source.authorize())
85 | .queryParam("response_type", "code")
86 | .queryParam("client_id", config.clientId)
87 | .queryParam("redirect_uri", config.redirectUri)
88 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "user" : config.scope)
89 | .queryParam("state", getRealState(state))
90 | .build();
91 | }
92 | /**
93 | * 校验请求结果
94 | *
95 | * @param response 请求结果
96 | * @return 如果请求结果正常,则返回Exception
97 | */
98 | private void checkResponse(Dictionary dic)
99 | {
100 | if (dic.ContainsKey("code") && dic.getInt32("code") != 0)
101 | {
102 | throw new Exception($"{dic.getString("msg")}");
103 | }
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/DingTalkScanAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 | using Newtonsoft.Json;
9 | using DingTalk.Api;
10 | using DingTalk.Api.Response;
11 | using DingTalk.Api.Request;
12 |
13 | namespace Come.CollectiveOAuth.Request
14 | {
15 | public class DingTalkScanAuthRequest : DefaultAuthRequest
16 | {
17 | public DingTalkScanAuthRequest(ClientConfig config) : base(config, new DingTalkScanAuthSource())
18 | {
19 | }
20 |
21 | public DingTalkScanAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
22 | : base(config, new DingTalkScanAuthSource(), authStateCache)
23 | {
24 | }
25 |
26 |
27 | protected override AuthToken getAccessToken(AuthCallback authCallback)
28 | {
29 | var authToken = new AuthToken();
30 | authToken.accessCode = authCallback.code;
31 | return authToken;
32 | }
33 |
34 | protected override AuthUser getUserInfo(AuthToken authToken)
35 | {
36 | var client = new DefaultDingTalkClient(source.userInfo());
37 | OapiSnsGetuserinfoBycodeRequest req = new OapiSnsGetuserinfoBycodeRequest();
38 | req.TmpAuthCode = authToken.accessCode;
39 | OapiSnsGetuserinfoBycodeResponse response = client.Execute(req, config.clientId, config.clientSecret);
40 |
41 | if (response.IsError)
42 | {
43 | throw new Exception(response.Errmsg);
44 | }
45 | var userObj = response.UserInfo;
46 |
47 | authToken.openId = userObj.Openid;
48 | authToken.unionId = userObj.Unionid;
49 |
50 | var authUser = new AuthUser();
51 | authUser.uuid = userObj.Unionid;
52 | authUser.username = userObj.Nick;
53 | authUser.nickname = userObj.Nick;
54 | authUser.gender = AuthUserGender.UNKNOWN;
55 |
56 | authUser.token = authToken;
57 | authUser.source = source.getName();
58 | authUser.originalUser = response;
59 | authUser.originalUserStr = JsonConvert.SerializeObject(response);
60 | return authUser;
61 |
62 | }
63 |
64 | /**
65 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
66 | *
67 | * @param state state 验证授权流程的参数,可以防止csrf
68 | * @return 返回授权地址
69 | * @since 1.9.3
70 | */
71 | public override string authorize(string state)
72 | {
73 | return UrlBuilder.fromBaseUrl(source.authorize())
74 | .queryParam("response_type", "code")
75 | .queryParam("appid", config.clientId)
76 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "snsapi_login" : config.scope)
77 | .queryParam("redirect_uri", config.redirectUri)
78 | .queryParam("state", getRealState(state))
79 | .build();
80 | }
81 |
82 | }
83 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/FackbookAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class FackbookAuthRequest : DefaultAuthRequest
12 | {
13 | public FackbookAuthRequest(ClientConfig config) : base(config, new FackbookAuthSource())
14 | {
15 | }
16 |
17 | public FackbookAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new FackbookAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | var response = doPostAuthorizationCode(authCallback.code);
25 | var accessTokenObject = response.parseObject();
26 | this.checkResponse(accessTokenObject);
27 |
28 | var authToken = new AuthToken
29 | {
30 | accessToken = accessTokenObject.getString("access_token"),
31 | expireIn = accessTokenObject.getInt32("expires_in"),
32 | tokenType = accessTokenObject.getString("token_type"),
33 | code = authCallback.code
34 | };
35 | return authToken;
36 | }
37 |
38 | protected override AuthUser getUserInfo(AuthToken authToken)
39 | {
40 | var response = doGetUserInfo(authToken);
41 | var userObj = response.parseObject();
42 | this.checkResponse(userObj);
43 |
44 | var authUser = new AuthUser
45 | {
46 | uuid = userObj.getString("id"),
47 | username = userObj.getString("name"),
48 | nickname = userObj.getString("name"),
49 | avatar = getUserPicture(userObj),
50 | location = userObj.getString("locale"),
51 | email = userObj.getString("email"),
52 | gender = GlobalAuthUtil.getRealGender(userObj.getString("gender")),
53 | token = authToken,
54 | source = source.getName(),
55 | originalUser = userObj,
56 | originalUserStr = response
57 | };
58 | return authUser;
59 | }
60 |
61 | private string getUserPicture(Dictionary userObj)
62 | {
63 | string picture = null;
64 | if (userObj.ContainsKey("picture"))
65 | {
66 | var pictureObj = userObj.getString("picture").parseObject();
67 | pictureObj = pictureObj.getString("data").parseObject();
68 | if (null != pictureObj)
69 | {
70 | picture = pictureObj.getString("url");
71 | }
72 | }
73 | return picture;
74 | }
75 |
76 | /**
77 | * 返回获取userInfo的url
78 | *
79 | * @param authToken 用户token
80 | * @return 返回获取userInfo的url
81 | */
82 | protected override string userInfoUrl(AuthToken authToken)
83 | {
84 | return UrlBuilder.fromBaseUrl(source.userInfo())
85 | .queryParam("access_token", authToken.accessToken)
86 | .queryParam("fields", "id,name,birthday,gender,hometown,email,devices,picture.width(400)")
87 | .build();
88 | }
89 |
90 |
91 | /**
92 | * 检查响应内容是否正确
93 | *
94 | * @param object 请求响应内容
95 | */
96 | private void checkResponse(Dictionary dic)
97 | {
98 | if (dic.ContainsKey("error"))
99 | {
100 | throw new Exception($"{dic.getString("error").parseObject().getString("message")}");
101 | }
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/GiteeAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Enums;
4 | using Come.CollectiveOAuth.Models;
5 | using Come.CollectiveOAuth.Utils;
6 | using System;
7 | using System.Collections.Generic;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class GiteeAuthRequest : DefaultAuthRequest
12 | {
13 | public GiteeAuthRequest(ClientConfig config) : base(config, new GiteeAuthSource())
14 | {
15 | }
16 |
17 | public GiteeAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new GiteeAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | string response = doPostAuthorizationCode(authCallback.code);
25 | var accessTokenObject = response.parseObject();
26 | this.checkResponse(accessTokenObject);
27 |
28 | var authToken = new AuthToken();
29 | authToken.accessToken = accessTokenObject.getString("access_token");
30 | authToken.refreshToken = accessTokenObject.getString("refresh_token");
31 | authToken.tokenType = accessTokenObject.getString("token_type");
32 | authToken.expireIn = accessTokenObject.getInt32("expires_in");
33 | authToken.scope = accessTokenObject.getString("scope");
34 |
35 | return authToken;
36 | }
37 |
38 | protected override AuthUser getUserInfo(AuthToken authToken)
39 | {
40 | string response = doGetUserInfo(authToken);
41 | var userObj = response.parseObject();
42 | this.checkResponse(userObj);
43 |
44 | var authUser = new AuthUser();
45 | authUser.uuid = userObj.getString("id");
46 | authUser.username = userObj.getString("login");
47 | authUser.nickname = userObj.getString("name");
48 | authUser.avatar = userObj.getString("avatar_url");
49 | authUser.blog = userObj.getString("blog");
50 | authUser.company = userObj.getString("company");
51 | authUser.location = userObj.getString("address");
52 | authUser.email = userObj.getString("email");
53 | authUser.remark = userObj.getString("bio");
54 | authUser.gender = AuthUserGender.UNKNOWN;
55 | authUser.token = authToken;
56 | authUser.source = source.getName();
57 | authUser.originalUser = userObj;
58 | authUser.originalUserStr = response;
59 | return authUser;
60 | }
61 |
62 |
63 | /**
64 | * 校验请求结果
65 | *
66 | * @param response 请求结果
67 | * @return 如果请求结果正常,则返回Exception
68 | */
69 | private void checkResponse(Dictionary dic)
70 | {
71 | if (dic.ContainsKey("error"))
72 | {
73 | throw new Exception($"{dic.getString("error_description")}");
74 | }
75 | }
76 | }
77 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/GithubAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class GithubAuthRequest : DefaultAuthRequest
12 | {
13 | public GithubAuthRequest(ClientConfig config) : base(config, new GithubAuthSource())
14 | {
15 | }
16 |
17 | public GithubAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new GithubAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | string response = doPostAuthorizationCode(authCallback.code);
25 | var accessTokenObject = response.parseStringObject();
26 | this.checkResponse(accessTokenObject);
27 |
28 | var authToken = new AuthToken();
29 | authToken.accessToken = accessTokenObject.getString("access_token");
30 | authToken.tokenType = accessTokenObject.getString("token_type");
31 | authToken.scope = accessTokenObject.getString("scope");
32 | authToken.code = authCallback.code;
33 |
34 | return authToken;
35 | }
36 |
37 | protected override AuthUser getUserInfo(AuthToken authToken)
38 | {
39 | string response = doGetUserInfo(authToken);
40 | var userObj = response.parseObject();
41 | this.checkResponse(userObj);
42 |
43 | var authUser = new AuthUser();
44 | authUser.uuid = userObj.getString("id");
45 | authUser.username = userObj.getString("login");
46 | authUser.nickname = userObj.getString("name");
47 | authUser.avatar = userObj.getString("avatar_url");
48 | authUser.blog = userObj.getString("blog");
49 | authUser.company = userObj.getString("company");
50 | authUser.location = userObj.getString("location");
51 | authUser.email = userObj.getString("email");
52 | authUser.remark = userObj.getString("bio");
53 | authUser.gender = AuthUserGender.UNKNOWN;
54 | authUser.token = authToken;
55 | authUser.source = source.getName();
56 | authUser.originalUser = userObj;
57 | authUser.originalUserStr = response;
58 | return authUser;
59 | }
60 |
61 | ///
62 | /// 重写获取用户信息方法
63 | ///
64 | ///
65 | ///
66 | protected override string doGetUserInfo(AuthToken authToken)
67 | {
68 | return HttpUtils.RequestJsonGet(userInfoUrl(authToken));
69 | }
70 |
71 | /**
72 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
73 | *
74 | * @param state state 验证授权流程的参数,可以防止csrf
75 | * @return 返回授权地址
76 | * @since 1.9.3
77 | */
78 | public override string authorize(string state)
79 | {
80 | return UrlBuilder.fromBaseUrl(source.authorize())
81 | .queryParam("client_id", config.clientId)
82 | .queryParam("response_type", "code")
83 | .queryParam("redirect_uri", config.redirectUri)
84 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "user" : config.scope)
85 | .queryParam("state", getRealState(state) + "#wechat_redirect")
86 | .build();
87 | }
88 |
89 | /**
90 | * 校验请求结果
91 | *
92 | * @param response 请求结果
93 | * @return 如果请求结果正常,则返回Exception
94 | */
95 | private void checkResponse(Dictionary dic)
96 | {
97 | if (dic.ContainsKey("error"))
98 | {
99 | throw new Exception($"{dic.getString("error_description")}");
100 | }
101 | }
102 | }
103 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/GitlabAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class GitlabAuthRequest : DefaultAuthRequest
12 | {
13 | public GitlabAuthRequest(ClientConfig config) : base(config, new GitlabAuthSource())
14 | {
15 | }
16 |
17 | public GitlabAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new GitlabAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | var response = doPostAuthorizationCode(authCallback.code);
25 | var accessTokenObject = response.parseObject();
26 |
27 | this.checkResponse(accessTokenObject);
28 |
29 | var authToken = new AuthToken();
30 | authToken.accessToken = accessTokenObject.getString("access_token");
31 | authToken.refreshToken = accessTokenObject.getString("refresh_token");
32 | authToken.idToken = accessTokenObject.getString("id_token");
33 | authToken.tokenType = accessTokenObject.getString("token_type");
34 | authToken.scope = accessTokenObject.getString("scope");
35 | authToken.code = authCallback.code;
36 |
37 | return authToken;
38 | }
39 |
40 |
41 | protected override AuthUser getUserInfo(AuthToken authToken)
42 | {
43 | var response = doGetUserInfo(authToken);
44 | var userObj = response.parseObject();
45 |
46 | this.checkResponse(userObj);
47 |
48 | var authUser = new AuthUser();
49 | authUser.uuid = userObj.getString("id");
50 | authUser.username = userObj.getString("username");
51 | authUser.nickname = userObj.getString("name");
52 | authUser.avatar = userObj.getString("avatar_url");
53 | authUser.blog = userObj.getString("web_url");
54 | authUser.company = userObj.getString("organization");
55 | authUser.location = userObj.getString("location");
56 | authUser.email = userObj.getString("email");
57 | authUser.remark = userObj.getString("bio");
58 | authUser.gender = AuthUserGender.UNKNOWN;
59 |
60 | authUser.token = authToken;
61 | authUser.source = source.getName();
62 | authUser.originalUser = userObj;
63 | authUser.originalUserStr = response;
64 | return authUser;
65 | }
66 |
67 |
68 | /**
69 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
70 | *
71 | * @param state state 验证授权流程的参数,可以防止csrf
72 | * @return 返回授权地址
73 | * @since 1.11.0
74 | */
75 | public override string authorize(string state)
76 | {
77 | return UrlBuilder.fromBaseUrl(source.authorize())
78 | .queryParam("response_type", "code")
79 | .queryParam("client_id", config.clientId)
80 | .queryParam("redirect_uri", config.redirectUri)
81 | .queryParam("state", getRealState(state))
82 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "read_user+openid+profile+email" : config.scope)
83 | .build();
84 | }
85 |
86 | /**
87 | * 校验请求结果
88 | *
89 | * @param response 请求结果
90 | * @return 如果请求结果正常,则返回Exception
91 | */
92 | private void checkResponse(Dictionary dic)
93 | {
94 | if (dic.ContainsKey("error"))
95 | {
96 | throw new Exception($"{dic.getString("error_description")}");
97 | }
98 | // user 验证异常
99 | if (dic.ContainsKey("message"))
100 | {
101 | throw new Exception($"{dic.getString("message")}");
102 | }
103 | }
104 |
105 | }
106 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/GoogleAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class GoogleAuthRequest : DefaultAuthRequest
12 | {
13 | public GoogleAuthRequest(ClientConfig config) : base(config, new GoogleAuthSource())
14 | {
15 | }
16 |
17 | public GoogleAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new GoogleAuthSource(), authStateCache)
19 | {
20 | }
21 | protected override AuthToken getAccessToken(AuthCallback authCallback)
22 | {
23 | var response = doPostAuthorizationCode(authCallback.code);
24 | var accessTokenObject = response.parseObject();
25 | this.checkResponse(accessTokenObject);
26 |
27 | var authToken = new AuthToken();
28 | authToken.accessToken = accessTokenObject.getString("access_token");
29 | authToken.expireIn = accessTokenObject.getInt32("expires_in");
30 | authToken.idToken = accessTokenObject.getString("id_token");
31 | authToken.tokenType = accessTokenObject.getString("token_type");
32 | authToken.scope = accessTokenObject.getString("scope");
33 |
34 | return authToken;
35 | }
36 |
37 | protected override AuthUser getUserInfo(AuthToken authToken)
38 | {
39 | var reqParams = new Dictionary
40 | {
41 | { "Authorization", "Bearer " + authToken.accessToken }
42 | };
43 | var response = HttpUtils.RequestPost(userInfoUrl(authToken), null, reqParams);
44 | var userInfo = response;
45 | var userObj = userInfo.parseObject();
46 | this.checkResponse(userObj);
47 |
48 | var authUser = new AuthUser();
49 | authUser.uuid = userObj.getString("sub");
50 | authUser.username = userObj.getString("email");
51 | authUser.nickname = userObj.getString("name");
52 | authUser.avatar = userObj.getString("picture");
53 | authUser.location = userObj.getString("locale");
54 | authUser.email = userObj.getString("email");
55 | authUser.gender = AuthUserGender.UNKNOWN;
56 |
57 | authUser.token = authToken;
58 | authUser.source = source.getName();
59 | authUser.originalUser = userObj;
60 | authUser.originalUserStr = response;
61 | return authUser;
62 | }
63 |
64 | /**
65 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
66 | *
67 | * @param state state 验证授权流程的参数,可以防止csrf
68 | * @return 返回授权地址
69 | * @since 1.9.3
70 | */
71 | public override string authorize(string state)
72 | {
73 | return UrlBuilder.fromBaseUrl(source.authorize())
74 | .queryParam("response_type", "code")
75 | .queryParam("client_id", config.clientId)
76 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "openid%20email%20profile" : config.scope)
77 | .queryParam("redirect_uri", config.redirectUri)
78 | .queryParam("state", getRealState(state))
79 | .build();
80 | }
81 |
82 | /**
83 | * 返回获取userInfo的url
84 | *
85 | * @param authToken 用户授权后的token
86 | * @return 返回获取userInfo的url
87 | */
88 | protected override string userInfoUrl(AuthToken authToken)
89 | {
90 | return UrlBuilder.fromBaseUrl(source.userInfo())
91 | .queryParam("access_token", authToken.accessToken)
92 | .build();
93 | }
94 |
95 | /**
96 | * 校验请求结果
97 | *
98 | * @param response 请求结果
99 | * @return 如果请求结果正常,则返回Exception
100 | */
101 | private void checkResponse(Dictionary dic)
102 | {
103 | if (dic.ContainsKey("error") || dic.ContainsKey("error_description"))
104 | {
105 | throw new Exception($"{dic.getString("error")}: {dic.getString("error_description")}");
106 | }
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/KujialeAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class KujialeAuthRequest : DefaultAuthRequest
12 | {
13 | public KujialeAuthRequest(ClientConfig config) : base(config, new KujialeAuthSource())
14 | {
15 | }
16 |
17 | public KujialeAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new KujialeAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | /**
23 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
24 | * 默认只向用户请求用户信息授权
25 | *
26 | * @param state state 验证授权流程的参数,可以防止csrf
27 | * @return 返回授权地址
28 | * @since 1.11.0
29 | */
30 | public override string authorize(string state)
31 | {
32 | var urlBuilder = UrlBuilder.fromBaseUrl(source.authorize())
33 | .queryParam("response_type", "code")
34 | .queryParam("client_id", config.clientId)
35 | .queryParam("redirect_uri", config.redirectUri)
36 | .queryParam("state", getRealState(state))
37 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "get_user_info": config.scope)
38 | .build();
39 | return urlBuilder;
40 | }
41 |
42 | protected override AuthToken getAccessToken(AuthCallback authCallback)
43 | {
44 | var response = doPostAuthorizationCode(authCallback.code);
45 | return getAuthToken(response);
46 | }
47 |
48 | private AuthToken getAuthToken(string response)
49 | {
50 | var accessTokenObject = response.parseObject();
51 | this.checkResponse(accessTokenObject);
52 |
53 | var resultObject = accessTokenObject.getJSONObject("d");
54 |
55 | var authToken = new AuthToken();
56 | authToken.accessToken = resultObject.getString("accessToken");
57 | authToken.refreshToken = resultObject.getString("refreshToken");
58 | authToken.expireIn = resultObject.getInt32("expiresIn");
59 | return authToken;
60 | }
61 |
62 |
63 | protected override AuthUser getUserInfo(AuthToken authToken)
64 | {
65 | string openId = this.getOpenId(authToken);
66 |
67 | var userInfoUrl = UrlBuilder.fromBaseUrl(source.userInfo())
68 | .queryParam("access_token", authToken.accessToken)
69 | .queryParam("open_id", openId)
70 | .build();
71 |
72 | var response = HttpUtils.RequestGet(userInfoUrl);
73 | var resObj = response.parseObject();
74 | this.checkResponse(resObj);
75 |
76 | var userObj = resObj.getJSONObject("d");
77 |
78 | var authUser = new AuthUser();
79 | authUser.uuid = userObj.getString("openId");
80 | authUser.username = userObj.getString("userName");
81 | authUser.nickname = userObj.getString("userName");
82 | authUser.avatar = userObj.getString("avatar");
83 | authUser.gender = AuthUserGender.UNKNOWN;
84 |
85 | authUser.token = authToken;
86 | authUser.source = source.getName();
87 | authUser.originalUser = resObj;
88 | authUser.originalUserStr = response;
89 | return authUser;
90 | }
91 |
92 | /**
93 | * 获取酷家乐的openId,此id在当前client范围内可以唯一识别授权用户
94 | *
95 | * @param authToken 通过{@link AuthKujialeRequest#getAccessToken(AuthCallback)}获取到的{@code authToken}
96 | * @return openId
97 | */
98 | private string getOpenId(AuthToken authToken)
99 | {
100 | var openIdUrl = UrlBuilder.fromBaseUrl("https://oauth.kujiale.com/oauth2/auth/user")
101 | .queryParam("access_token", authToken.accessToken)
102 | .build();
103 | var response = HttpUtils.RequestGet(openIdUrl);
104 | var accessTokenObject = response.parseObject();
105 | this.checkResponse(accessTokenObject);
106 | return accessTokenObject.getString("d");
107 | }
108 |
109 | public override AuthResponse refresh(AuthToken authToken)
110 | {
111 | var refreshUrl = refreshTokenUrl(authToken.refreshToken);
112 | var response = HttpUtils.RequestPost(refreshUrl);
113 | return new AuthResponse(AuthResponseStatus.SUCCESS.GetCode(), AuthResponseStatus.SUCCESS.GetDesc(), getAuthToken(response));
114 | }
115 |
116 | /**
117 | * 校验请求结果
118 | *
119 | * @param response 请求结果
120 | * @return 如果请求结果正常,则返回Exception
121 | */
122 | private void checkResponse(Dictionary dic)
123 | {
124 | if (dic.Count == 0)
125 | {
126 | throw new Exception("请求所返回的数据为空!");
127 | }
128 |
129 | if (!"0".Equals(dic.getString("c")))
130 | {
131 | throw new Exception($"{dic.getString("m")}");
132 | }
133 | }
134 | }
135 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/MeituanAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class MeituanAuthRequest : DefaultAuthRequest
12 | {
13 | public MeituanAuthRequest(ClientConfig config) : base(config, new MeituanAuthSource())
14 | {
15 | }
16 |
17 | public MeituanAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new MeituanAuthSource(), authStateCache)
19 | {
20 | }
21 | protected override AuthToken getAccessToken(AuthCallback authCallback)
22 | {
23 | var reqParams = new Dictionary
24 | {
25 | { "app_id", config.clientId },
26 | { "secret", config.clientSecret },
27 | { "code", authCallback.code },
28 | { "grant_type", "authorization_code" },
29 | };
30 |
31 | var response = HttpUtils.RequestFormPost(source.accessToken(), reqParams.spellParams());
32 | var accessTokenObject = response.parseObject();
33 |
34 | this.checkResponse(accessTokenObject);
35 |
36 | var authToken = new AuthToken
37 | {
38 | accessToken = accessTokenObject.getString("access_token"),
39 | expireIn = accessTokenObject.getInt32("expires_in"),
40 | refreshToken = accessTokenObject.getString("refresh_token"),
41 | code = authCallback.code
42 | };
43 |
44 | return authToken;
45 | }
46 |
47 | protected override AuthUser getUserInfo(AuthToken authToken)
48 | {
49 | var reqParams = new Dictionary
50 | {
51 | { "app_id", config.clientId },
52 | { "secret", config.clientSecret },
53 | { "access_token", authToken.accessToken },
54 | };
55 |
56 | var response = HttpUtils.RequestFormPost(source.userInfo(), reqParams.spellParams());
57 | var userObj = response.parseObject();
58 |
59 | this.checkResponse(userObj);
60 |
61 | var authUser = new AuthUser
62 | {
63 | uuid = userObj.getString("openid"),
64 | username = userObj.getString("nickname"),
65 | nickname = userObj.getString("nickname"),
66 | avatar = userObj.getString("avatar"),
67 | gender = AuthUserGender.UNKNOWN,
68 | token = authToken,
69 | source = source.getName(),
70 | originalUser = userObj,
71 | originalUserStr = response
72 | };
73 | return authUser;
74 | }
75 |
76 | public override AuthResponse refresh(AuthToken oldToken)
77 | {
78 | var reqParams = new Dictionary
79 | {
80 | { "app_id", config.clientId },
81 | { "secret", config.clientSecret },
82 | { "refresh_token", oldToken.refreshToken },
83 | { "grant_type", "refresh_token" },
84 | };
85 |
86 | var response = HttpUtils.RequestFormPost(source.refresh(), reqParams.spellParams());
87 | var accessTokenObject = response.parseObject();
88 |
89 | this.checkResponse(accessTokenObject);
90 |
91 | var authToken = new AuthToken
92 | {
93 | accessToken = accessTokenObject.getString("access_token"),
94 | refreshToken = accessTokenObject.getString("refresh_token"),
95 | expireIn = accessTokenObject.getInt32("expires_in")
96 | };
97 |
98 | return new AuthResponse(AuthResponseStatus.SUCCESS.GetCode(), AuthResponseStatus.SUCCESS.GetDesc(), authToken);
99 | }
100 |
101 |
102 | public override string authorize(string state)
103 | {
104 | return UrlBuilder.fromBaseUrl(source.authorize())
105 | .queryParam("response_type", "code")
106 | .queryParam("app_id", config.clientId)
107 | .queryParam("redirect_uri", config.redirectUri)
108 | .queryParam("state", getRealState(state))
109 | .queryParam("scope", config.scope)
110 | .build();
111 | }
112 |
113 |
114 | /**
115 | * 校验请求结果
116 | *
117 | * @param response 请求结果
118 | * @return 如果请求结果正常,则返回Exception
119 | */
120 | private void checkResponse(Dictionary dic)
121 | {
122 | if (dic.ContainsKey("error_code"))
123 | {
124 | throw new Exception($"{dic.getString("error_msg")}");
125 | }
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/OschinaAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class OschinaAuthRequest : DefaultAuthRequest
12 | {
13 | public OschinaAuthRequest(ClientConfig config) : base(config, new OschinaAuthSource())
14 | {
15 | }
16 |
17 | public OschinaAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new OschinaAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | string response = doPostAuthorizationCode(authCallback.code);
25 | var accessTokenObject = response.parseObject();
26 | this.checkResponse(accessTokenObject);
27 |
28 | var authToken = new AuthToken();
29 | authToken.accessToken = accessTokenObject.getString("access_token");
30 | authToken.refreshToken = accessTokenObject.getString("refresh_token");
31 | authToken.uid = accessTokenObject.getString("uid");
32 | authToken.expireIn = accessTokenObject.getInt32("expires_in");
33 | authToken.code = authCallback.code;
34 | return authToken;
35 | }
36 |
37 | protected override AuthUser getUserInfo(AuthToken authToken)
38 | {
39 | string response = doGetUserInfo(authToken);
40 |
41 | var userObj = response.parseObject();
42 | this.checkResponse(userObj);
43 |
44 | var authUser = new AuthUser();
45 | authUser.uuid = userObj.getString("id");
46 | authUser.username = userObj.getString("name");
47 | authUser.nickname = userObj.getString("name");
48 | authUser.avatar = userObj.getString("avatar");
49 | authUser.blog = userObj.getString("url");
50 | authUser.location = userObj.getString("location");
51 | authUser.email = userObj.getString("email");
52 | authUser.gender = GlobalAuthUtil.getRealGender(userObj.getString("gender"));
53 |
54 | authUser.token = authToken;
55 | authUser.source = source.getName();
56 | authUser.originalUser = userObj;
57 | authUser.originalUserStr = response;
58 | return authUser;
59 | }
60 |
61 | /**
62 | * 返回获取accessToken的url
63 | *
64 | * @param code 授权回调时带回的授权码
65 | * @return 返回获取accessToken的url
66 | */
67 | protected override string accessTokenUrl(string code)
68 | {
69 | return UrlBuilder.fromBaseUrl(source.accessToken())
70 | .queryParam("code", code)
71 | .queryParam("client_id", config.clientId)
72 | .queryParam("client_secret", config.clientSecret)
73 | .queryParam("grant_type", "authorization_code")
74 | .queryParam("redirect_uri", config.redirectUri)
75 | .queryParam("dataType", "json")
76 | .build();
77 | }
78 |
79 | /**
80 | * 返回获取userInfo的url
81 | *
82 | * @param authToken 用户授权后的token
83 | * @return 返回获取userInfo的url
84 | */
85 | protected override string userInfoUrl(AuthToken authToken)
86 | {
87 | return UrlBuilder.fromBaseUrl(source.userInfo())
88 | .queryParam("access_token", authToken.accessToken)
89 | .queryParam("dataType", "json")
90 | .build();
91 | }
92 |
93 |
94 | /**
95 | * 校验请求结果
96 | *
97 | * @param response 请求结果
98 | * @return 如果请求结果正常,则返回Exception
99 | */
100 | private void checkResponse(Dictionary dic)
101 | {
102 | if (dic.ContainsKey("error"))
103 | {
104 | throw new Exception($"{dic.getString("error_description")}");
105 | }
106 | }
107 | }
108 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/PinterestAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class PinterestAuthRequest : DefaultAuthRequest
12 | {
13 | public PinterestAuthRequest(ClientConfig config) : base(config, new PinterestAuthSource())
14 | {
15 | }
16 |
17 | public PinterestAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new PinterestAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | var response = doPostAuthorizationCode(authCallback.code);
25 | var accessTokenObject = response.parseObject();
26 | this.checkResponse(accessTokenObject);
27 |
28 | var authToken = new AuthToken
29 | {
30 | accessToken = accessTokenObject.getString("access_token"),
31 | tokenType = accessTokenObject.getString("token_type"),
32 | code = authCallback.code
33 | };
34 |
35 | return authToken;
36 | }
37 |
38 |
39 | protected override AuthUser getUserInfo(AuthToken authToken)
40 | {
41 | string userinfoUrl = userInfoUrl(authToken);
42 | var response = HttpUtils.RequestGet(userinfoUrl);
43 | var responseObj = response.parseObject();
44 | this.checkResponse(responseObj);
45 |
46 | var userObj = responseObj.getString("data").parseObject();
47 |
48 | var authUser = new AuthUser();
49 | authUser.uuid = userObj.getString("id");
50 | authUser.username = userObj.getString("username");
51 | authUser.nickname = userObj.getString("first_name") + userObj.getString("last_name");
52 | authUser.avatar = getAvatarUrl(userObj);
53 | authUser.remark = userObj.getString("bio");
54 | authUser.gender = AuthUserGender.UNKNOWN;
55 | authUser.token = authToken;
56 | authUser.source = source.getName();
57 | authUser.originalUser = responseObj;
58 | authUser.originalUserStr = response;
59 | return authUser;
60 | }
61 |
62 |
63 | private string getAvatarUrl(Dictionary userObj)
64 | {
65 | // image is a map data structure
66 | var jsonObject = userObj.getString("image").parseObject();
67 | if (jsonObject.Count == 0)
68 | {
69 | return null;
70 | }
71 | return jsonObject.getString("60x60").parseObject().getString("url");
72 | }
73 |
74 | /**
75 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
76 | *
77 | * @param state state 验证授权流程的参数,可以防止csrf
78 | * @return 返回授权地址
79 | * @since 1.9.3
80 | */
81 | public override string authorize(string state)
82 | {
83 | return UrlBuilder.fromBaseUrl(source.authorize())
84 | .queryParam("response_type", "code")
85 | .queryParam("client_id", config.clientId)
86 | .queryParam("redirect_uri", config.redirectUri)
87 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "read_public": config.scope)
88 | .queryParam("state", getRealState(state))
89 | .build();
90 | }
91 |
92 | /**
93 | * 返回获取userInfo的url
94 | *
95 | * @param authToken token
96 | * @return 返回获取userInfo的url
97 | */
98 | protected override string userInfoUrl(AuthToken authToken)
99 | {
100 | return UrlBuilder.fromBaseUrl(source.userInfo())
101 | .queryParam("access_token", authToken.accessToken)
102 | .queryParam("fields", "id,username,first_name,last_name,bio,image")
103 | .build();
104 | }
105 |
106 |
107 | /**
108 | * 检查响应内容是否正确
109 | *
110 | * @param object 请求响应内容
111 | */
112 | private void checkResponse(Dictionary dic)
113 | {
114 | if (dic.ContainsKey("status") && "failure".Equals(dic.getString("status")))
115 | {
116 | throw new Exception($"{dic.getString("message")}");
117 | }
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/RenrenAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class RenrenAuthRequest : DefaultAuthRequest
12 | {
13 | public RenrenAuthRequest(ClientConfig config) : base(config, new RenrenAuthSource())
14 | {
15 | }
16 |
17 | public RenrenAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new RenrenAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | return this.getToken(accessTokenUrl(authCallback.code));
25 | }
26 |
27 | protected override AuthUser getUserInfo(AuthToken authToken)
28 | {
29 | var response = doGetUserInfo(authToken);
30 | var userObj = response.parseObject().getJSONObject("response");
31 |
32 | var authUser = new AuthUser();
33 | authUser.uuid = userObj.getString("id");
34 | authUser.username = userObj.getString("name");
35 | authUser.nickname = userObj.getString("name");
36 | authUser.avatar = getAvatarUrl(userObj);
37 | authUser.company = getCompany(userObj);
38 | authUser.gender = getGender(userObj);
39 |
40 | authUser.token = authToken;
41 | authUser.source = source.getName();
42 | authUser.originalUser = userObj;
43 | authUser.originalUserStr = response;
44 | return authUser;
45 | }
46 |
47 | public override AuthResponse refresh(AuthToken authToken)
48 | {
49 | var token = getToken(this.refreshTokenUrl(authToken.refreshToken));
50 | return new AuthResponse(AuthResponseStatus.SUCCESS.GetCode(), AuthResponseStatus.SUCCESS.GetDesc(), token);
51 | }
52 |
53 | private AuthToken getToken(string url)
54 | {
55 | var response = HttpUtils.RequestPost(url);
56 | var jsonObject = response.parseObject();
57 | if (jsonObject.ContainsKey("error"))
58 | {
59 | throw new Exception("Failed to get token from Renren: " + jsonObject);
60 | }
61 |
62 | var authToken = new AuthToken();
63 | authToken.accessToken = jsonObject.getString("access_token");
64 | authToken.tokenType = jsonObject.getString("token_type");
65 | authToken.expireIn = jsonObject.getInt32("expires_in");
66 | authToken.refreshToken = jsonObject.getString("refresh_token");
67 | authToken.openId = jsonObject.getJSONObject("user").getString("id");
68 |
69 | return authToken;
70 | }
71 |
72 | private string getAvatarUrl(Dictionary userObj)
73 | {
74 | var jsonArray = userObj.getJSONArray("avatar");
75 | if (jsonArray.Count == 0)
76 | {
77 | return null;
78 | }
79 | return jsonArray[0].getString("url");
80 | }
81 |
82 | private AuthUserGender getGender(Dictionary userObj)
83 | {
84 | var basicInformation = userObj.getJSONObject("basicInformation");
85 | if (basicInformation.Count == 0)
86 | {
87 | return AuthUserGender.UNKNOWN;
88 | }
89 | return GlobalAuthUtil.getRealGender(basicInformation.getString("sex"));
90 | }
91 |
92 | private string getCompany(Dictionary userObj)
93 | {
94 | var jsonArray = userObj.getJSONArray("work");
95 | if (jsonArray.Count == 0)
96 | {
97 | return null;
98 | }
99 | return jsonArray[0].getString("name");
100 | }
101 |
102 | /**
103 | * 返回获取userInfo的url
104 | *
105 | * @param authToken 用户授权后的token
106 | * @return 返回获取userInfo的url
107 | */
108 | protected override string userInfoUrl(AuthToken authToken)
109 | {
110 | return UrlBuilder.fromBaseUrl(source.userInfo())
111 | .queryParam("access_token", authToken.accessToken)
112 | .queryParam("userId", authToken.openId)
113 | .build();
114 | }
115 |
116 | public override string authorize(string state)
117 | {
118 | return UrlBuilder.fromBaseUrl(source.authorize())
119 | .queryParam("response_type", "code")
120 | .queryParam("client_id", config.clientId)
121 | .queryParam("redirect_uri", config.redirectUri)
122 | .queryParam("state", getRealState(state))
123 | .queryParam("display", "page")
124 | .build();
125 | }
126 | }
127 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/StackOverflowAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class StackOverflowAuthRequest : DefaultAuthRequest
12 | {
13 | public StackOverflowAuthRequest(ClientConfig config) : base(config, new StackOverflowAuthSource())
14 | {
15 | }
16 |
17 | public StackOverflowAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new StackOverflowAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | string accessTokenUrl = this.accessTokenUrl(authCallback.code);
25 |
26 | var reqHeaders = new Dictionary
27 | {
28 | { "Content-Type", "application/x-www-form-urlencoded" },
29 | };
30 | var reqParams = accessTokenUrl.parseUrlObject();
31 |
32 | var response = HttpUtils.RequestPost(source.accessToken(), reqParams.spellParams(), reqHeaders);
33 |
34 | var accessTokenObject = response.parseObject();
35 | this.checkResponse(accessTokenObject);
36 |
37 | var authToken = new AuthToken();
38 | authToken.accessToken = accessTokenObject.getString("access_token");
39 | authToken.expireIn = accessTokenObject.getInt32("expires");
40 | return authToken;
41 | }
42 |
43 |
44 | protected override AuthUser getUserInfo(AuthToken authToken)
45 | {
46 | string userInfoUrl = UrlBuilder.fromBaseUrl(this.source.userInfo())
47 | .queryParam("access_token", authToken.accessToken)
48 | .queryParam("site", "stackoverflow")
49 | .queryParam("key", this.config.stackOverflowKey)
50 | .build();
51 |
52 | var response = HttpUtils.RequestGet(userInfoUrl);
53 | var responseObj = response.parseObject();
54 | this.checkResponse(responseObj);
55 | var userObj = responseObj.getString("items").parseListObject()[0];
56 |
57 | var authUser = new AuthUser();
58 | authUser.uuid = userObj.getString("user_id");
59 | authUser.username = userObj.getString("username");
60 | authUser.nickname = userObj.getString("display_name");
61 | authUser.avatar = userObj.getString("profile_image");
62 | authUser.location = userObj.getString("location");
63 |
64 | authUser.gender = AuthUserGender.UNKNOWN;
65 | authUser.token = authToken;
66 | authUser.source = source.getName();
67 | authUser.originalUser = responseObj;
68 | authUser.originalUserStr = response;
69 | return authUser;
70 | }
71 |
72 | /**
73 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
74 | *
75 | * @param state state 验证授权流程的参数,可以防止csrf
76 | * @return 返回授权地址
77 | * @since 1.9.3
78 | */
79 |
80 | public override string authorize(string state)
81 | {
82 | return UrlBuilder.fromBaseUrl(source.authorize())
83 | .queryParam("response_type", "code")
84 | .queryParam("client_id", config.clientId)
85 | .queryParam("redirect_uri", config.redirectUri)
86 | .queryParam("scope", config.scope.IsNullOrWhiteSpace() ? "read_inbox" : config.scope)
87 | .queryParam("state", getRealState(state))
88 | .build();
89 | }
90 |
91 |
92 | /**
93 | * 检查响应内容是否正确
94 | *
95 | * @param object 请求响应内容
96 | */
97 | private void checkResponse(Dictionary dic)
98 | {
99 | if (dic.ContainsKey("error"))
100 | {
101 | throw new Exception($"{dic.getString("error_description")}");
102 | }
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/TeambitionAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 | using Newtonsoft.Json;
9 |
10 | namespace Come.CollectiveOAuth.Request
11 | {
12 | public class TeambitionAuthRequest : DefaultAuthRequest
13 | {
14 | public TeambitionAuthRequest(ClientConfig config) : base(config, new GithubAuthSource())
15 | {
16 | }
17 |
18 | public TeambitionAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
19 | : base(config, new GithubAuthSource(), authStateCache)
20 | {
21 | }
22 |
23 | protected override AuthToken getAccessToken(AuthCallback authCallback)
24 | {
25 | var reqHeaders = new Dictionary
26 | {
27 | { "Content-Type", "application/x-www-form-urlencoded" },
28 | };
29 | var reqParams = new Dictionary
30 | {
31 | { "client_id", config.clientId },
32 | { "client_secret", config.clientSecret },
33 | { "code", authCallback.code },
34 | { "grant_type", "code" },
35 | };
36 |
37 | var response = HttpUtils.RequestPost(source.accessToken(), reqParams.spellParams(), reqHeaders);
38 |
39 | var accessTokenObject = response.parseObject();
40 |
41 | this.checkResponse(accessTokenObject);
42 |
43 | var authToken = new AuthToken();
44 | authToken.accessToken = accessTokenObject.getString("access_token");
45 | authToken.refreshToken = accessTokenObject.getString("refresh_token");
46 |
47 | return authToken;
48 | }
49 |
50 | protected override AuthUser getUserInfo(AuthToken authToken)
51 | {
52 | var accessToken = authToken.accessToken;
53 | var reqHeaders = new Dictionary
54 | {
55 | { "Authorization", "OAuth2 " + accessToken },
56 | };
57 |
58 | var response = HttpUtils.RequestGet(source.userInfo(), reqHeaders);
59 | var userObj = response.parseObject();
60 |
61 | this.checkResponse(userObj);
62 | authToken.uid = userObj.getString("_id");
63 |
64 | var authUser = new AuthUser();
65 | authUser.uuid = userObj.getString("_id");
66 | authUser.username = userObj.getString("name");
67 | authUser.nickname = userObj.getString("name");
68 | authUser.avatar = userObj.getString("avatarUrl");
69 | authUser.blog = userObj.getString("website");
70 | authUser.location = userObj.getString("location");
71 | authUser.email = userObj.getString("email");
72 | authUser.gender = AuthUserGender.UNKNOWN;
73 | authUser.token = authToken;
74 | authUser.source = source.getName();
75 | authUser.originalUser = userObj;
76 | authUser.originalUserStr = response;
77 | return authUser;
78 | }
79 |
80 |
81 | public override AuthResponse refresh(AuthToken oldToken)
82 | {
83 | string uid = oldToken.uid;
84 | string refreshToken = oldToken.refreshToken;
85 | var reqHeaders = new Dictionary
86 | {
87 | { "Content-Type", "application/x-www-form-urlencoded" },
88 | };
89 | var reqParams = new Dictionary
90 | {
91 | { "_userId", uid },
92 | { "refresh_token", refreshToken },
93 | };
94 |
95 | var response = HttpUtils.RequestPost(source.refresh(), reqParams.spellParams(), reqHeaders);
96 |
97 | var refreshTokenObject = response.parseObject();
98 |
99 | this.checkResponse(refreshTokenObject);
100 |
101 | var authToken = new AuthToken();
102 | authToken.accessToken = refreshTokenObject.getString("access_token");
103 | authToken.refreshToken = refreshTokenObject.getString("refresh_token");
104 |
105 | return new AuthResponse(AuthResponseStatus.SUCCESS.GetCode(), AuthResponseStatus.SUCCESS.GetDesc(), authToken);
106 | }
107 |
108 |
109 | /**
110 | * 校验请求结果
111 | *
112 | * @param response 请求结果
113 | * @return 如果请求结果正常,则返回Exception
114 | */
115 | private void checkResponse(Dictionary dic)
116 | {
117 | if (dic.ContainsKey("message") && dic.ContainsKey("name"))
118 | {
119 | throw new Exception($"{dic.getString("getString")}, {dic.getString("name")}");
120 | }
121 | }
122 | }
123 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/ToutiaoAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using Come.CollectiveOAuth.Enums;
9 |
10 | namespace Come.CollectiveOAuth.Request
11 | {
12 | public class ToutiaoAuthRequest : DefaultAuthRequest
13 | {
14 | public ToutiaoAuthRequest(ClientConfig config) : base(config, new ToutiaoAuthSource())
15 | {
16 | }
17 |
18 | public ToutiaoAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
19 | : base(config, new ToutiaoAuthSource(), authStateCache)
20 | {
21 | }
22 |
23 | protected override AuthToken getAccessToken(AuthCallback authCallback)
24 | {
25 | var response = doGetAuthorizationCode(authCallback.code);
26 | var accessTokenObject = response.parseObject();
27 |
28 | this.checkResponse(accessTokenObject);
29 |
30 | var authToken = new AuthToken();
31 | authToken.accessToken = accessTokenObject.getString("access_token");
32 | authToken.expireIn = accessTokenObject.getInt32("expires_in");
33 | authToken.openId = accessTokenObject.getString("open_id");
34 | authToken.code = authCallback.code;
35 | return authToken;
36 | }
37 |
38 | protected override AuthUser getUserInfo(AuthToken authToken)
39 | {
40 | string userResponse = doGetUserInfo(authToken);
41 | var userProfile = userResponse.parseObject();
42 | this.checkResponse(userProfile);
43 |
44 | var userObj = userProfile.getString("data").parseObject();
45 |
46 | bool isAnonymousUser = userObj.getInt32("uid_type") == 14;
47 | string anonymousUserName = "匿名用户";
48 |
49 | var authUser = new AuthUser();
50 | authUser.uuid = userObj.getString("uid");
51 | authUser.username = isAnonymousUser ? anonymousUserName : userObj.getString("screen_name");
52 | authUser.nickname = isAnonymousUser ? anonymousUserName : userObj.getString("screen_name");
53 | authUser.avatar = userObj.getString("avatar_url");
54 | authUser.remark = userObj.getString("description");
55 | authUser.gender = GlobalAuthUtil.getRealGender(userObj.getString("gender"));
56 | authUser.token = authToken;
57 | authUser.source = source.getName();
58 | authUser.originalUser = userProfile;
59 | authUser.originalUserStr = userResponse;
60 | return authUser;
61 | }
62 |
63 | /**
64 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
65 | *
66 | * @param state state 验证授权流程的参数,可以防止csrf
67 | * @return 返回授权地址
68 | * @since 1.9.3
69 | */
70 | public override string authorize(string state)
71 | {
72 | return UrlBuilder.fromBaseUrl(source.authorize())
73 | .queryParam("response_type", "code")
74 | .queryParam("client_key", config.clientId)
75 | .queryParam("redirect_uri", config.redirectUri)
76 | .queryParam("auth_only", 1)
77 | .queryParam("display", 0)
78 | .queryParam("state", getRealState(state))
79 | .build();
80 | }
81 |
82 | /**
83 | * 返回获取accessToken的url
84 | *
85 | * @param code 授权码
86 | * @return 返回获取accessToken的url
87 | */
88 | protected override string accessTokenUrl(string code)
89 | {
90 | return UrlBuilder.fromBaseUrl(source.accessToken())
91 | .queryParam("code", code)
92 | .queryParam("client_key", config.clientId)
93 | .queryParam("client_secret", config.clientSecret)
94 | .queryParam("grant_type", "authorization_code")
95 | .build();
96 | }
97 |
98 | /**
99 | * 返回获取userInfo的url
100 | *
101 | * @param authToken 用户授权后的token
102 | * @return 返回获取userInfo的url
103 | */
104 | protected override string userInfoUrl(AuthToken authToken)
105 | {
106 | return UrlBuilder.fromBaseUrl(source.userInfo())
107 | .queryParam("client_key", config.clientId)
108 | .queryParam("access_token", authToken.accessToken)
109 | .build();
110 | }
111 |
112 | /**
113 | * 校验请求结果
114 | *
115 | * @param response 请求结果
116 | * @return 如果请求结果正常,则返回Exception
117 | */
118 | private void checkResponse(Dictionary dic)
119 | {
120 | if (dic.ContainsKey("error_code"))
121 | {
122 | throw new Exception(getToutiaoErrorCode(dic.getInt32("error_code")).GetDesc());
123 | }
124 | }
125 |
126 | private AuthToutiaoErrorCode getToutiaoErrorCode(int errorCode)
127 | {
128 | var enumObjects = typeof(AuthToutiaoErrorCode).ToList();
129 | var codeEnum = enumObjects.Where(a => a.ID == errorCode).ToList();
130 | if (codeEnum.Count > 0)
131 | {
132 | return GlobalAuthUtil.enumFromString(codeEnum[0].Name);
133 | }
134 | else
135 | {
136 | return AuthToutiaoErrorCode.EC999;
137 | }
138 | }
139 | }
140 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/WeChatEnterpriseScanAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Enums;
4 | using Come.CollectiveOAuth.Models;
5 | using Come.CollectiveOAuth.Utils;
6 | using System;
7 | using System.Collections.Generic;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class WeChatEnterpriseScanAuthRequest : DefaultAuthRequest
12 | {
13 | public WeChatEnterpriseScanAuthRequest(ClientConfig config) : base(config, new WechatEnterpriseScanAuthSource())
14 | {
15 | }
16 |
17 | public WeChatEnterpriseScanAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new WechatEnterpriseScanAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | /**
23 | * 微信的特殊性,此时返回的信息同时包含 openid 和 access_token
24 | *
25 | * @param authCallback 回调返回的参数
26 | * @return 所有信息
27 | */
28 | protected override AuthToken getAccessToken(AuthCallback authCallback)
29 | {
30 | string response = doGetAuthorizationCode(accessTokenUrl(authCallback.code));
31 | var jsonObj = response.parseObject();
32 |
33 | this.checkResponse(jsonObj);
34 |
35 | var authToken = new AuthToken();
36 | authToken.accessToken = jsonObj.getString("access_token");
37 | authToken.expireIn = jsonObj.getInt32("expires_in");
38 | authToken.code = authCallback.code;
39 |
40 | return authToken;
41 | }
42 |
43 | protected override AuthUser getUserInfo(AuthToken authToken)
44 | {
45 | string response = doGetUserInfo(authToken);
46 | var jsonObj = response.parseObject();
47 | this.checkResponse(jsonObj);
48 |
49 | // 返回 OpenId 或其他,均代表非当前企业用户,不支持
50 | if (!jsonObj.ContainsKey("UserId"))
51 | {
52 | throw new Exception(AuthResponseStatus.UNIDENTIFIED_PLATFORM.GetDesc());
53 | }
54 | string userId = jsonObj.getString("UserId");
55 | string userDetailResponse = getUserDetail(authToken.accessToken, userId);
56 | var userDetailObj = userDetailResponse.parseObject();
57 | this.checkResponse(userDetailObj);
58 |
59 | var authUser = new AuthUser();
60 | authUser.username = userDetailObj.getString("name");
61 | authUser.nickname = userDetailObj.getString("alias");
62 | authUser.avatar = userDetailObj.getString("avatar");
63 | authUser.location = userDetailObj.getString("address");
64 | authUser.email = userDetailObj.getString("email");
65 | authUser.uuid = userDetailObj.getString("userId");
66 | authUser.token = authToken;
67 | authUser.source = source.getName();
68 | authUser.gender = GlobalAuthUtil.getWechatRealGender(userDetailObj.getString("gender"));
69 |
70 | authUser.originalUser = userDetailObj;
71 | authUser.originalUserStr = response;
72 | return authUser;
73 | }
74 |
75 | /**
76 | * 校验请求结果
77 | *
78 | * @param response 请求结果
79 | * @return 如果请求结果正常,则返回JSONObject
80 | */
81 | private void checkResponse(Dictionary dic)
82 | {
83 | if (dic.ContainsKey("errcode") && dic.getInt32("errcode") != 0)
84 | {
85 | throw new Exception($"errcode: {dic.getString("errcode")}, errmsg: {dic.getString("errmsg")}");
86 | }
87 | }
88 |
89 | /**
90 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
91 | *
92 | * @param state state 验证授权流程的参数,可以防止csrf
93 | * @return 返回授权地址
94 | * @since 1.9.3
95 | */
96 | public override string authorize(string state)
97 | {
98 | return UrlBuilder.fromBaseUrl(source.authorize())
99 | .queryParam("appid", config.clientId)
100 | .queryParam("agentid", config.agentId)
101 | .queryParam("redirect_uri", config.redirectUri)
102 | .queryParam("state", getRealState(state))
103 | .build();
104 | }
105 |
106 | /**
107 | * 返回获取accessToken的url
108 | *
109 | * @param code 授权码
110 | * @return 返回获取accessToken的url
111 | */
112 | protected override string accessTokenUrl(String code)
113 | {
114 | return UrlBuilder.fromBaseUrl(source.accessToken())
115 | .queryParam("corpid", config.clientId)
116 | .queryParam("corpsecret", config.clientSecret)
117 | .build();
118 | }
119 |
120 | /**
121 | * 返回获取userInfo的url
122 | *
123 | * @param authToken 用户授权后的token
124 | * @return 返回获取userInfo的url
125 | */
126 | protected override string userInfoUrl(AuthToken authToken)
127 | {
128 | return UrlBuilder.fromBaseUrl(source.userInfo())
129 | .queryParam("access_token", authToken.accessToken)
130 | .queryParam("code", authToken.code)
131 | .build();
132 | }
133 |
134 | /**
135 | * 用户详情
136 | *
137 | * @param accessToken accessToken
138 | * @param userId 企业内用户id
139 | * @return 用户详情
140 | */
141 | private string getUserDetail(string accessToken, string userId)
142 | {
143 | string userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
144 | .queryParam("access_token", accessToken)
145 | .queryParam("userid", userId)
146 | .build();
147 | return HttpUtils.RequestGet(userDetailUrl);
148 | }
149 | }
150 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/AuthRequests/WeiboAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Cache;
2 | using Come.CollectiveOAuth.Config;
3 | using Come.CollectiveOAuth.Models;
4 | using Come.CollectiveOAuth.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using Come.CollectiveOAuth.Enums;
8 |
9 | namespace Come.CollectiveOAuth.Request
10 | {
11 | public class WeiboAuthRequest : DefaultAuthRequest
12 | {
13 | public WeiboAuthRequest(ClientConfig config) : base(config, new WeiboAuthSource())
14 | {
15 | }
16 |
17 | public WeiboAuthRequest(ClientConfig config, IAuthStateCache authStateCache)
18 | : base(config, new WeiboAuthSource(), authStateCache)
19 | {
20 | }
21 |
22 | protected override AuthToken getAccessToken(AuthCallback authCallback)
23 | {
24 | var response = doPostAuthorizationCode(authCallback.code);
25 | var accessTokenObject = response.parseObject();
26 | if (accessTokenObject.ContainsKey("error"))
27 | {
28 | throw new Exception(accessTokenObject.getString("error_description"));
29 | }
30 |
31 | var authToken = new AuthToken();
32 | authToken.accessToken = accessTokenObject.getString("access_token");
33 | authToken.uid = accessTokenObject.getString("uid");
34 | authToken.openId = accessTokenObject.getString("uid");
35 | authToken.expireIn = accessTokenObject.getInt32("expires_in");
36 | authToken.code = authCallback.code;
37 |
38 | return authToken;
39 | }
40 |
41 | protected override AuthUser getUserInfo(AuthToken authToken)
42 | {
43 | var accessToken = authToken.accessToken;
44 | var uid = authToken.uid;
45 | var oauthParam = $"uid={uid}&access_token={accessToken}";
46 | var reqParams = new Dictionary();
47 | reqParams.Add("Authorization", "OAuth2 " + oauthParam);
48 | reqParams.Add("API-RemoteIP", "application/x-www-form-urlencoded");
49 |
50 | string response = HttpUtils.RequestGet(userInfoUrl(authToken), reqParams);
51 |
52 | var userObj = response.parseObject();
53 | if (userObj.ContainsKey("error"))
54 | {
55 | throw new Exception(userObj.getString("error"));
56 | }
57 |
58 | var authUser = new AuthUser();
59 | authUser.uuid = userObj.getString("id");
60 | authUser.username = userObj.getString("name");
61 | authUser.nickname = userObj.getString("screen_name");
62 | authUser.avatar = userObj.getString("profile_image_url");
63 | authUser.blog = userObj.getString("url").IsNullOrWhiteSpace() ? $"{"https://weibo.com/"}{userObj.getString("profile_url")}" : userObj.getString("url");
64 | authUser.location = userObj.getString("location");
65 | authUser.remark = userObj.getString("description");
66 | authUser.gender = GlobalAuthUtil.getRealGender(userObj.getString("gender"));
67 |
68 | authUser.token = authToken;
69 | authUser.source = source.getName();
70 | authUser.originalUser = userObj;
71 | authUser.originalUserStr = response;
72 | return authUser;
73 | }
74 |
75 | /**
76 | * 返回获取userInfo的url
77 | *
78 | * @param authToken authToken
79 | * @return 返回获取userInfo的url
80 | */
81 | protected override string userInfoUrl(AuthToken authToken)
82 | {
83 | return UrlBuilder.fromBaseUrl(source.userInfo())
84 | .queryParam("access_token", authToken.accessToken)
85 | .queryParam("uid", authToken.uid)
86 | .build();
87 | }
88 |
89 | public override AuthResponse revoke(AuthToken authToken)
90 | {
91 | var response = doGetRevoke(authToken);
92 | var retObj = response.parseObject();
93 | if (retObj.ContainsKey("error"))
94 | {
95 | return new AuthResponse(AuthResponseStatus.FAILURE.GetCode(), retObj.getString("error"));
96 | }
97 | // 返回 result = true 表示取消授权成功,否则失败
98 | AuthResponseStatus status = retObj.getBool("result") ? AuthResponseStatus.SUCCESS : AuthResponseStatus.FAILURE;
99 | return new AuthResponse(status.GetCode(), status.GetDesc());
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Request/IAuthRequest.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Models;
2 |
3 | namespace Come.CollectiveOAuth.Request
4 | {
5 | /**
6 | * JustAuth {@code Request}公共接口,所有平台的{@code Request}都需要实现该接口
7 | *
8 | * {@link AuthRequest#authorize()}
9 | * {@link AuthRequest#authorize(string)}
10 | * {@link AuthRequest#login(AuthCallback)}
11 | * {@link AuthRequest#revoke(AuthToken)}
12 | * {@link AuthRequest#refresh(AuthToken)}
13 | *
14 | * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
15 | * @since 1.8
16 | */
17 | public interface IAuthRequest
18 | {
19 | /**
20 | * 返回授权url,可自行跳转页面
21 | *
22 | * 不建议使用该方式获取授权地址,不带{@code state}的授权地址,容易受到csrf攻击。
23 | * 建议使用{@link AuthDefaultRequest#authorize(string)}方法生成授权地址,在回调方法中对{@code state}进行校验
24 | *
25 | * @return 返回授权地址
26 | */
27 | string authorize();
28 |
29 | /**
30 | * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
31 | *
32 | * @param state state 验证授权流程的参数,可以防止csrf
33 | * @return 返回授权地址
34 | */
35 | string authorize(string state);
36 |
37 | /**
38 | * 第三方登录
39 | *
40 | * @param authCallback 用于接收回调参数的实体
41 | * @return 返回登录成功后的用户信息
42 | */
43 | AuthResponse login(AuthCallback authCallback);
44 |
45 | /**
46 | * 撤销授权
47 | *
48 | * @param authToken 登录成功后返回的Token信息
49 | * @return AuthResponse
50 | */
51 | AuthResponse revoke(AuthToken authToken);
52 |
53 | /**
54 | * 刷新access token (续期)
55 | *
56 | * @param authToken 登录成功后返回的Token信息
57 | * @return AuthResponse
58 | */
59 | AuthResponse refresh(AuthToken authToken);
60 | }
61 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Utils/AppSettingUtils.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Come.CollectiveOAuth.Utils
3 | {
4 | public class AppSettingUtils
5 | {
6 | ///
7 | /// 根据Key取Value值
8 | ///
9 | ///
10 | public static string GetStrValue(string key)
11 | {
12 | var value = "";
13 | #if NET45
14 | value = System.Configuration.ConfigurationManager.AppSettings[key];
15 | #else
16 | value = Come.CollectiveOAuth.Utils.ConfigurationManager.AppSettings[key];
17 | #endif
18 | if (!string.IsNullOrWhiteSpace(value))
19 | {
20 | return value.ToString().Trim();
21 | }
22 | return value;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Utils/AuthChecker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Come.CollectiveOAuth.Cache;
4 | using Come.CollectiveOAuth.Config;
5 | using Come.CollectiveOAuth.Enums;
6 | using Come.CollectiveOAuth.Models;
7 |
8 | namespace Come.CollectiveOAuth.Utils
9 | {
10 | public class AuthChecker
11 | {
12 | /**
13 | * 是否支持第三方登录
14 | *
15 | * @param config config
16 | * @param source source
17 | * @return true or false
18 | * @since 1.6.1-beta
19 | */
20 | public static bool isSupportedAuth(ClientConfig config, IAuthSource source)
21 | {
22 |
23 | bool isSupported = !string.IsNullOrWhiteSpace(config.clientId) && !string.IsNullOrWhiteSpace(config.clientSecret) && !string.IsNullOrWhiteSpace(config.redirectUri);
24 | /*if (isSupported && DefaultAuthSource.ALIPAY == source)
25 | {
26 | isSupported = StringUtils.isNotEmpty(config.getAlipayPublicKey());
27 | }
28 | if (isSupported && AuthDefaultSource.STACK_OVERFLOW == source)
29 | {
30 | isSupported = StringUtils.isNotEmpty(config.getStackOverflowKey());
31 | }
32 | if (isSupported && AuthDefaultSource.WECHAT_ENTERPRISE == source)
33 | {
34 | isSupported = StringUtils.isNotEmpty(config.getAgentId());
35 | }*/
36 |
37 |
38 |
39 | return isSupported;
40 | }
41 |
42 |
43 | /**
44 | * 检查配置合法性。针对部分平台, 对redirect uri有特定要求。一般来说redirect uri都是http://,而对于facebook平台, redirect uri 必须是https的链接
45 | *
46 | * @param config config
47 | * @param source source
48 | * @since 1.6.1-beta
49 | */
50 | public static void checkConfig(ClientConfig config, IAuthSource source)
51 | {
52 | string redirectUri = config.redirectUri;
53 | if (!GlobalAuthUtil.isHttpProtocol(redirectUri) && !GlobalAuthUtil.isHttpsProtocol(redirectUri))
54 | {
55 | throw new Exception(AuthResponseStatus.ILLEGAL_REDIRECT_URI.GetDesc());
56 | }
57 | // facebook的回调地址必须为https的链接
58 | if ("FACEBOOK".Equals(source.getName().ToUpper()) && !GlobalAuthUtil.isHttpsProtocol(redirectUri))
59 | {
60 | // Facebook's redirect uri must use the HTTPS protocol
61 | throw new Exception(AuthResponseStatus.ILLEGAL_REDIRECT_URI.GetDesc());
62 | }
63 | // 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1
64 | if ("ALIPAY".Equals(source.getName().ToUpper()) && GlobalAuthUtil.isLocalHost(redirectUri))
65 | {
66 | // The redirect uri of alipay is forbidden to use localhost or 127.0.0.1
67 | throw new Exception(AuthResponseStatus.ILLEGAL_REDIRECT_URI.GetDesc());
68 | }
69 | }
70 |
71 | /**
72 | * 校验回调传回的code
73 | *
74 | * {@code v1.10.0}版本中改为传入{@code source}和{@code callback},对于不同平台使用不同参数接受code的情况统一做处理
75 | *
76 | * @param source 当前授权平台
77 | * @param callback 从第三方授权回调回来时传入的参数集合
78 | * @since 1.8.0
79 | */
80 | public static void checkCode(IAuthSource source, AuthCallback callback)
81 | {
82 | string code = callback.code;
83 | if (source.getName().ToUpper().Equals(DefaultAuthSourceEnum.ALIPAY_MP.ToString()))
84 | {
85 | code = callback.auth_code;
86 | }
87 | else if ("HUAWEI".Equals(source.getName().ToUpper()))
88 | {
89 | code = callback.authorization_code;
90 | }
91 | if (string.IsNullOrWhiteSpace(code))
92 | {
93 | throw new Exception(AuthResponseStatus.ILLEGAL_CODE.GetDesc());
94 | }
95 | }
96 |
97 | /**
98 | * 校验回调传回的{@code state},为空或者不存在
99 | *
100 | * {@code state}不存在的情况只有两种:
101 | * 1. {@code state}已使用,被正常清除
102 | * 2. {@code state}为前端伪造,本身就不存在
103 | *
104 | * @param state {@code state}一定不为空
105 | * @param authStateCache {@code authStateCache} state缓存实现
106 | */
107 | public static void checkState(string state, IAuthSource source, IAuthStateCache authStateCache)
108 | {
109 | if (string.IsNullOrWhiteSpace(state) || !authStateCache.containsKey(state))
110 | {
111 | throw new Exception(AuthResponseStatus.ILLEGAL_STATUS.GetDesc());
112 | }
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Utils/AuthStateUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Come.CollectiveOAuth.Utils
4 | {
5 | public class AuthStateUtils
6 | {
7 | /**
8 | * 生成随机state,采用https://github.com/lets-mica/mica的UUID工具
9 | *
10 | * @return 随机的state字符串
11 | */
12 | public static string createState()
13 | {
14 | return Guid.NewGuid().ToString();
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/Come.CollectiveOAuth/Utils/UrlBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Come.CollectiveOAuth.Utils
5 | {
6 | public class UrlBuilder
7 | {
8 | private Dictionary paramDic = new Dictionary();
9 | private string baseUrl;
10 |
11 | private UrlBuilder()
12 | {
13 |
14 | }
15 |
16 | /**
17 | * @param baseUrl 基础路径
18 | * @return the new {@code UrlBuilder}
19 | */
20 | public static UrlBuilder fromBaseUrl(string baseUrl)
21 | {
22 | UrlBuilder builder = new UrlBuilder();
23 | builder.baseUrl = baseUrl;
24 | return builder;
25 | }
26 |
27 | /**
28 | * 添加参数
29 | *
30 | * @param key 参数名称
31 | * @param value 参数值
32 | * @return this UrlBuilder
33 | */
34 | public UrlBuilder queryParam(string key, object value)
35 | {
36 | if (string.IsNullOrWhiteSpace(key))
37 | {
38 | throw new Exception("参数名不能为空");
39 | }
40 |
41 | string valueAsString = (value != null ? Convert.ToString(value) : null);
42 | this.paramDic.Add(key, valueAsString);
43 | return this;
44 | }
45 |
46 | /**
47 | * 构造url
48 | *
49 | * @return url
50 | */
51 | public string build()
52 | {
53 | return this.build(false);
54 | }
55 |
56 | /**
57 | * 构造url
58 | *
59 | * @param encode 转码
60 | * @return url
61 | */
62 | public string build(bool encode)
63 | {
64 | if (this.paramDic.Count == 0 || this.paramDic == null)
65 | {
66 | return this.baseUrl;
67 | }
68 | string baseUrl = this.appendIfNotContain(this.baseUrl, "?", "&");
69 | string paramString = GlobalAuthUtil.parseMapToString(this.paramDic);
70 | return baseUrl + paramString;
71 | }
72 |
73 | /**
74 | * 如果给定字符串{@code str}中不包含{@code appendStr},则在{@code str}后追加{@code appendStr};
75 | * 如果已包含{@code appendStr},则在{@code str}后追加{@code otherwise}
76 | *
77 | * @param str 给定的字符串
78 | * @param appendStr 需要追加的内容
79 | * @param otherwise 当{@code appendStr}不满足时追加到{@code str}后的内容
80 | * @return 追加后的字符串
81 | */
82 | public string appendIfNotContain(string str, string appendStr, string otherwise)
83 | {
84 | if (string.IsNullOrWhiteSpace(str) || string.IsNullOrWhiteSpace(appendStr))
85 | {
86 | return str;
87 | }
88 | if (str.Contains(appendStr))
89 | {
90 | return str + otherwise;
91 | }
92 | return str + appendStr;
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/Come.Web.Sample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29519.87
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Come.Web.Sample", "Come.Web.Sample\Come.Web.Sample.csproj", "{8F544C63-C74C-4C28-9120-2896C292A686}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Come.CollectiveOAuth", "Come.CollectiveOAuth\Come.CollectiveOAuth.csproj", "{6D482ED4-236A-484B-9810-DFEE702A5541}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Come.AspNetCore.Sample", "Come.AspNetCore.Sample\Come.AspNetCore.Sample.csproj", "{ED0A91E3-47C4-44D8-8F88-643B1E0C225D}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {8F544C63-C74C-4C28-9120-2896C292A686}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {8F544C63-C74C-4C28-9120-2896C292A686}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {8F544C63-C74C-4C28-9120-2896C292A686}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {8F544C63-C74C-4C28-9120-2896C292A686}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {6D482ED4-236A-484B-9810-DFEE702A5541}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {6D482ED4-236A-484B-9810-DFEE702A5541}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {6D482ED4-236A-484B-9810-DFEE702A5541}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {6D482ED4-236A-484B-9810-DFEE702A5541}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {ED0A91E3-47C4-44D8-8F88-643B1E0C225D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {ED0A91E3-47C4-44D8-8F88-643B1E0C225D}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {ED0A91E3-47C4-44D8-8F88-643B1E0C225D}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {ED0A91E3-47C4-44D8-8F88-643B1E0C225D}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {E026076A-ED44-4D1B-BFAE-2636CE19223D}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/Come.Web.Sample/74859ed3c048d2f62d27ffb52db3badc.html:
--------------------------------------------------------------------------------
1 | This file is used to verify domain ownership, please upload it to the root directory of your domain name, thank you. By Xiaomi Company
--------------------------------------------------------------------------------
/Come.Web.Sample/App_Start/BundleConfig.cs:
--------------------------------------------------------------------------------
1 | using System.Web;
2 | using System.Web.Optimization;
3 |
4 | namespace Come.Web.Sample
5 | {
6 | public class BundleConfig
7 | {
8 | // 有关捆绑的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkId=301862
9 | public static void RegisterBundles(BundleCollection bundles)
10 | {
11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
12 | "~/Scripts/jquery-{version}.js"));
13 |
14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
15 | "~/Scripts/jquery.validate*"));
16 |
17 | // 使用要用于开发和学习的 Modernizr 的开发版本。然后,当你做好
18 | // 生产准备就绪,请使用 https://modernizr.com 上的生成工具仅选择所需的测试。
19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
20 | "~/Scripts/modernizr-*"));
21 |
22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
23 | "~/Scripts/bootstrap.js"));
24 |
25 | bundles.Add(new StyleBundle("~/Content/css").Include(
26 | "~/Content/bootstrap.css",
27 | "~/Content/site.css"));
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Come.Web.Sample/App_Start/FilterConfig.cs:
--------------------------------------------------------------------------------
1 | using System.Web;
2 | using System.Web.Mvc;
3 |
4 | namespace Come.Web.Sample
5 | {
6 | public class FilterConfig
7 | {
8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters)
9 | {
10 | filters.Add(new HandleErrorAttribute());
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Come.Web.Sample/App_Start/RouteConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Mvc;
6 | using System.Web.Routing;
7 |
8 | namespace Come.Web.Sample
9 | {
10 | public class RouteConfig
11 | {
12 | public static void RegisterRoutes(RouteCollection routes)
13 | {
14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
15 |
16 | routes.MapRoute(
17 | name: "Default",
18 | url: "{controller}/{action}/{id}",
19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
20 | );
21 |
22 | routes.MapRoute(
23 | name: "Come.Callback",
24 | url: "Home/Callback/{authSource}",
25 | defaults: new { controller = "Home", action = "Callback", authSource = UrlParameter.Optional }
26 | );
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Content/Site.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 50px;
3 | padding-bottom: 20px;
4 | }
5 |
6 | /* Set padding to keep content from hitting the edges */
7 | .body-content {
8 | padding-left: 15px;
9 | padding-right: 15px;
10 | }
11 |
12 | /* Override the default bootstrap behavior where horizontal description lists
13 | will truncate terms that are too long to fit in the left column
14 | */
15 | .dl-horizontal dt {
16 | white-space: normal;
17 | }
18 |
19 | /* Set width on the form input elements since they're 100% wide by default */
20 | input,
21 | select,
22 | textarea {
23 | max-width: 280px;
24 | }
25 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Mvc;
6 |
7 | namespace Come.Web.Sample.Controllers
8 | {
9 | public class HomeController : Controller
10 | {
11 | public ActionResult Index()
12 | {
13 | return View();
14 | }
15 |
16 | public ActionResult About()
17 | {
18 | ViewBag.Message = "Your application description page.";
19 |
20 | return View();
21 | }
22 |
23 | public ActionResult Contact()
24 | {
25 | ViewBag.Message = "Your contact page.";
26 |
27 | return View();
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Come.Web.Sample/Controllers/OAuth2Controller.cs:
--------------------------------------------------------------------------------
1 | using Come.CollectiveOAuth.Models;
2 | using Come.CollectiveOAuth.Utils;
3 | using Newtonsoft.Json;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Web;
8 | using System.Web.Mvc;
9 |
10 | namespace Come.Web.Sample.Controllers
11 | {
12 | public class OAuth2Controller : Controller
13 | {
14 |
15 | ///
16 | /// 构建授权Url方法
17 | ///
18 | ///
19 | /// RedirectUrl
20 | public ActionResult Authorization(string authSource)
21 | {
22 | AuthRequestFactory authRequest = new AuthRequestFactory();
23 | var request = authRequest.getRequest(authSource);
24 | var authorize = request.authorize(AuthStateUtils.createState());
25 | Console.WriteLine(authorize);
26 | return Redirect(authorize);
27 | }
28 |
29 | ///
30 | /// 授权回调方法
31 | ///
32 | ///
33 | ///
34 | ///
35 | public ActionResult Callback(string authSource, AuthCallback authCallback)
36 | {
37 | AuthRequestFactory authRequest = new AuthRequestFactory();
38 | var request = authRequest.getRequest(authSource);
39 | var authResponse = request.login(authCallback);
40 | return Content(JsonConvert.SerializeObject(authResponse));
41 | }
42 |
43 | ///
44 | /// 钉钉callback
45 | ///
46 | ///
47 | ///
48 | ///
49 | public ActionResult DingTalkCallback(AuthCallback authCallback)
50 | {
51 | AuthRequestFactory authRequest = new AuthRequestFactory();
52 | var request = authRequest.getRequest("DINGTALK_SCAN");
53 | var authResponse = request.login(authCallback);
54 | return Content(JsonConvert.SerializeObject(authResponse));
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/Come.Web.Sample/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Come.Web.Sample.MvcApplication" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Mvc;
6 | using System.Web.Optimization;
7 | using System.Web.Routing;
8 |
9 | namespace Come.Web.Sample
10 | {
11 | public class MvcApplication : System.Web.HttpApplication
12 | {
13 | protected void Application_Start()
14 | {
15 | AreaRegistration.RegisterAllAreas();
16 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
17 | RouteConfig.RegisterRoutes(RouteTable.Routes);
18 | BundleConfig.RegisterBundles(BundleTable.Bundles);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的常规信息是通过以下项进行控制的
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Come.Web.Sample")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Come.Web.Sample")]
13 | [assembly: AssemblyCopyright("版权所有(C) 2020")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 将使此程序集中的类型
18 | // 对 COM 组件不可见。如果需要
19 | // 从 COM 访问此程序集中的某个类型,请针对该类型将 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于 typelib 的 ID
23 | [assembly: Guid("c552e138-f6dd-49ef-a67e-6edea603691b")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 内部版本号
30 | // 修订版本
31 | //
32 | // 你可以指定所有值,也可以让修订版本和内部版本号采用默认值,
33 | // 方法是按如下所示使用 "*":
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Scripts/jquery.validate.unobtrusive.min.js:
--------------------------------------------------------------------------------
1 | // Unobtrusive validation support library for jQuery and jQuery Validate
2 | // Copyright (c) .NET Foundation. All rights reserved.
3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
4 | // @version v3.2.11
5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a(" ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive});
--------------------------------------------------------------------------------
/Come.Web.Sample/Views/Home/About.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewBag.Title = "About";
3 | }
4 | @ViewBag.Title.
5 | @ViewBag.Message
6 |
7 | Use this area to provide additional information.
8 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Views/Home/Contact.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewBag.Title = "Contact";
3 | }
4 | @ViewBag.Title.
5 | @ViewBag.Message
6 |
7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P:
11 | 425.555.0100
12 |
13 |
14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com
17 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Views/Shared/Error.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 错误
7 |
8 |
9 |
10 | 错误。
11 | 处理你的请求时出错。
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @ViewBag.Title
8 | @Styles.Render("~/Content/css")
9 | @Scripts.Render("~/bundles/modernizr")
10 |
11 |
12 |
13 |
14 |
22 |
23 |
24 | @Html.ActionLink("主页", "Index", "Home")
25 | @* @Html.ActionLink("关于", "About", "Home") *@
26 | @* @Html.ActionLink("联系方式", "Contact", "Home") *@
27 |
28 |
29 |
30 |
31 |
32 | @RenderBody()
33 |
34 |
37 |
38 |
39 | @Scripts.Render("~/bundles/jquery")
40 | @Scripts.Render("~/bundles/bootstrap")
41 | @RenderSection("scripts", required: false)
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Views/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "~/Views/Shared/_Layout.cshtml";
3 | }
4 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Come.Web.Sample/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Come.Web.Sample/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geekoutnet/CollectiveOAuth/ccab5ac92f048eb887a66ebdddd428391adb97eb/Come.Web.Sample/favicon.ico
--------------------------------------------------------------------------------
/Come.Web.Sample/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geekoutnet/CollectiveOAuth/ccab5ac92f048eb887a66ebdddd428391adb97eb/Come.Web.Sample/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Come.Web.Sample/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geekoutnet/CollectiveOAuth/ccab5ac92f048eb887a66ebdddd428391adb97eb/Come.Web.Sample/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Come.Web.Sample/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geekoutnet/CollectiveOAuth/ccab5ac92f048eb887a66ebdddd428391adb97eb/Come.Web.Sample/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Come.Web.Sample/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geekoutnet/CollectiveOAuth/ccab5ac92f048eb887a66ebdddd428391adb97eb/Come.Web.Sample/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/Come.Web.Sample/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/README.en.md:
--------------------------------------------------------------------------------
1 | # CollectiveOAuth
2 |
3 | #### Description
4 | .Net平台 史上最全的整合第三方登录的开源库。目前已支持Github、Gitee、钉钉、百度、支付宝、微信、企业微信、等第三方平台的授权登录。
5 | 以下平台正在接入中: 微博、Coding、腾讯云开发者平台、OSChina、QQ、淘宝、Google、Facebook、抖音、领英、小米、微软、今日头条、Teambition、StackOverflow、Pinterest、人人、华为、酷家乐、Gitlab、美团、饿了么和推特
6 |
7 | #### Software Architecture
8 | Software architecture description
9 |
10 | #### Installation
11 |
12 | 1. xxxx
13 | 2. xxxx
14 | 3. xxxx
15 |
16 | #### Instructions
17 |
18 | 1. xxxx
19 | 2. xxxx
20 | 3. xxxx
21 |
22 | #### Contribution
23 |
24 | 1. Fork the repository
25 | 2. Create Feat_xxx branch
26 | 3. Commit your code
27 | 4. Create Pull Request
28 |
29 |
30 | #### Gitee Feature
31 |
32 | 1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
33 | 2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
34 | 3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
35 | 4. The most valuable open source project [GVP](https://gitee.com/gvp)
36 | 5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
37 | 6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
38 |
--------------------------------------------------------------------------------