从 oauth 身份验证获取电子邮件 (Microsoft)

2024-04-17

如何从微软帐户获取电子邮件?我正在执行以下操作:

    public ActionResult ExternalLoginCallback(string returnUrl)
    {
    AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
//...

string email = null;
                if (result.Provider.ToLower() == "google")
                {
                    email = result.ExtraData["email"];
                }
                else if (result.Provider.ToLower() == "facebook")
                {
                    email = result.ExtraData["username"];
                }
                else if (result.Provider.ToLower() == "microsoft")
                {
                    email = result.ExtraData["????"];
                }    
}

对于谷歌和脸书我可以收到电子邮件,但我不能通过微软?我应该使用什么kew?


解决方案:

public class MicrosoftScopedClient : IAuthenticationClient
    {
        private string clientId;
        private string clientSecret;
        private string scope;

        private const string baseUrl = "https://login.live.com/oauth20_authorize.srf";
        private const string tokenUrl = "https://login.live.com/oauth20_token.srf";

        public MicrosoftScopedClient(string clientId, string clientSecret, string scope)
        {
            this.clientId = clientId;
            this.clientSecret = clientSecret;
            this.scope = scope;
        }

        public string ProviderName
        {
            get { return "Microsoft"; }
        }

        public void RequestAuthentication(HttpContextBase context, Uri returnUrl)
        {
            string url = baseUrl + "?client_id=" + clientId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=" + HttpUtility.UrlEncode(scope) + "&response_type=code";
            context.Response.Redirect(url);
        }

        public AuthenticationResult VerifyAuthentication(HttpContextBase context)
        {
            string code = context.Request.QueryString["code"];

            string rawUrl = context.Request.Url.ToString();
            //From this we need to remove code portion
            rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", "");

            IDictionary<string, string> userData = GetUserData(code, rawUrl);

            if (userData == null)
                return new AuthenticationResult(false, ProviderName, null, null, null);

            string id = userData["id"];
            string username = userData["email"];
            userData.Remove("id");
            userData.Remove("email");

            AuthenticationResult result = new AuthenticationResult(true, ProviderName, id, username, userData);
            return result;
        }

        private IDictionary<string, string> GetUserData(string accessCode, string redirectURI)
        {
            string token = QueryAccessToken(redirectURI, accessCode);
            if (token == null || token == "")
            {
                return null;
            }
            var userData = GetUserData(token);
            return userData;
        }

        private IDictionary<string, string> GetUserData(string accessToken)
        {
            ExtendedMicrosoftClientUserData graph;
            var request =
                WebRequest.Create(
                    "https://apis.live.net/v5.0/me?access_token=" + EscapeUriDataStringRfc3986(accessToken));
            using (var response = request.GetResponse())
            {
                using (var responseStream = response.GetResponseStream())
                {
                    using (StreamReader sr = new StreamReader(responseStream))
                    {
                        string data = sr.ReadToEnd();
                        graph = JsonConvert.DeserializeObject<ExtendedMicrosoftClientUserData>(data);
                    }
                }
            }

            var userData = new Dictionary<string, string>();
            userData.Add("id", graph.Id);
            userData.Add("username", graph.Name);
            userData.Add("name", graph.Name);
            userData.Add("link", graph.Link == null ? null : graph.Link.AbsoluteUri);
            userData.Add("gender", graph.Gender);
            userData.Add("firstname", graph.FirstName);
            userData.Add("lastname", graph.LastName);
            userData.Add("email", graph.Emails.Preferred);
            return userData;
        }

        private string QueryAccessToken(string returnUrl, string authorizationCode)
        {
            var entity =
                CreateQueryString(
                    new Dictionary<string, string> {
                        { "client_id", this.clientId },
                        { "redirect_uri", returnUrl },
                        { "client_secret", this.clientSecret},
                        { "code", authorizationCode },
                        { "grant_type", "authorization_code" },
                    });

            WebRequest tokenRequest = WebRequest.Create(tokenUrl);
            tokenRequest.ContentType = "application/x-www-form-urlencoded";
            tokenRequest.ContentLength = entity.Length;
            tokenRequest.Method = "POST";

            using (Stream requestStream = tokenRequest.GetRequestStream())
            {
                var writer = new StreamWriter(requestStream);
                writer.Write(entity);
                writer.Flush();
            }

            HttpWebResponse tokenResponse = (HttpWebResponse)tokenRequest.GetResponse();
            if (tokenResponse.StatusCode == HttpStatusCode.OK)
            {
                using (Stream responseStream = tokenResponse.GetResponseStream())
                {
                    using (StreamReader sr = new StreamReader(responseStream))
                    {
                        string data = sr.ReadToEnd();
                        var tokenData = JsonConvert.DeserializeObject<OAuth2AccessTokenData>(data);
                        if (tokenData != null)
                        {
                            return tokenData.AccessToken;
                        }
                    }
                }
            }

            return null;
        }

        private static readonly string[] UriRfc3986CharsToEscape = new[] { "!", "*", "'", "(", ")" };
        private static string EscapeUriDataStringRfc3986(string value)
        {
            StringBuilder escaped = new StringBuilder(Uri.EscapeDataString(value));

            // Upgrade the escaping to RFC 3986, if necessary.
            for (int i = 0; i < UriRfc3986CharsToEscape.Length; i++)
            {
                escaped.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0]));
            }

            // Return the fully-RFC3986-escaped string.
            return escaped.ToString();
        }

        private static string CreateQueryString(IEnumerable<KeyValuePair<string, string>> args)
        {
            if (!args.Any())
            {
                return string.Empty;
            }
            StringBuilder sb = new StringBuilder(args.Count() * 10);

            foreach (var p in args)
            {
                sb.Append(EscapeUriDataStringRfc3986(p.Key));
                sb.Append('=');
                sb.Append(EscapeUriDataStringRfc3986(p.Value));
                sb.Append('&');
            }
            sb.Length--; // remove trailing &

            return sb.ToString();
        }

        protected class ExtendedMicrosoftClientUserData
        {
            public string FirstName { get; set; }
            public string Gender { get; set; }
            public string Id { get; set; }
            public string LastName { get; set; }
            public Uri Link { get; set; }
            public string Name { get; set; }
            public Emails Emails { get; set; }
        }

        protected class Emails
        {
            public string Preferred { get; set; }
            public string Account { get; set; }
            public string Personal { get; set; }
            public string Business { get; set; }
        }
    }

AuthConfig.cs

public static class AuthConfig
    {
        public static void RegisterAuth()
        {

            Dictionary<string, object> MicrosoftsocialData = new Dictionary<string, object>();
            MicrosoftsocialData.Add("Icon", "../Content/icons/microsoft.png");

            OAuthWebSecurity.RegisterClient(new MicrosoftScopedClient("XXXXXXXX", "YYYYYYYYYYYYY",
                "wl.basic wl.emails"), "Microsoft", MicrosoftsocialData);

            //......
        }
    }

Usage:

public ActionResult ExternalLoginCallback(string returnUrl)
    {
    AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
//...

string email = null;
                if (result.Provider.ToLower() == "google")
                {
                    email = result.ExtraData["email"];
                }
                else if (result.Provider.ToLower() == "facebook")
                {
                    email = result.ExtraData["username"];
                }
                else if (result.Provider.ToLower() == "microsoft")
                {
                    email = result.UserName;
                }    
}

基于:OAuthWebSecurity如何获取不同oauth客户端的电子邮件,但Microsoft客户端不返回电子邮件,它不包含范围“wl.emails” http://mvcdiary.com/2013/03/01/how-oauthsecurity-to-obtain-emails-for-different-oauth-clients-but-microsoft-client-doesnt-return-email-it-didnt-include-scope-wl-emails/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 oauth 身份验证获取电子邮件 (Microsoft) 的相关文章

  • 通过 Instagram API 访问公共 Instagram 内容,且 accesstoken 不会过期

    我想显示来自 Instagram 的与特定主题标签相关的公共内容 一切正常 但我无法更新access token每次过期的时候 不要假设您的 access token 永远有效 https www instagram com develop
  • Windows Workflow Foundation 4 和 ASP.NET MVC

    我们正在评估 Windows Workflow Foundation 4 在基于 MVC 3 的 Web 应用程序中的使用 我们希望为不同的项目创建灵活的订单工作流程 有人知道有关此类应用程序的一般架构或实践实验室的详细信息吗 一些具体问题
  • ASP.NET MVC 4 会话超时

    我正在使用 VS 2012 IIS 7 5 开发一个带有 ASP NET MVC4 的互联网应用程序 我正在使用表单身份验证 我的网络配置中的设置如下
  • Spring Cloud Gateway + Spring安全资源服务器

    我真的不会把它放在这里 但我真的很困惑 我想实现以下目标 我在跑步 Java 14 Spring Cloud Gateway版本 Hoxton SR3 Spring Boot版本 2 2 5 RELEASE 现在我想将安全性集成到我的网关和
  • ASP MVC4 - 通过视图模型传递列表以查看

    我有一个模型人物 其中包括出生日期等字段 我想将所有人的列表以及每个人的计算年龄传递给视图 因此 视图模型 public class vm PersonList public Person Person get set public int
  • MVC4如何在没有导航属性的情况下加载相关数据

    我对 MVC 相当陌生 并且已经使用 EF database first 创建了一个 MVC4 应用程序 该数据库不包含外键定义 我无法添加它们 我不拥有该数据库 以下是数据库中的两个示例类 public partial class All
  • OAuth 2.0:优点和用例 - 为什么?

    谁能解释一下 OAuth2 的优点以及为什么我们应该实施它 我问这个问题是因为我对此有点困惑 这是我目前的想法 OAuth1 更准确地说是 HMAC 请求看起来合乎逻辑 易于理解 易于开发并且非常非常安全 相反 OAuth2 带来了授权请求
  • 何时应使用服务器端与客户端 Facebook 身份验证流程?

    Facebook 有两个身份验证流程 客户端和服务器端 每一项应该在什么时候使用 脸书文档 https developers facebook com docs authentication https developers faceboo
  • mvc3,你能给控制器一个显示名称吗?

    我用的是mvc3 是否可以为控制器和操作指定显示名称 DisplayName Facebook Employee public class EmployeeController Controller 在我的面包屑中 我将获得控制器名称和操作
  • 部署在 Azure 中时在 EF 迁移中使用更新数据库

    上下文 我在 Azure 中部署了 ASP NET MVC4 解决方案 我的 MSSQL Server 数据库也在 Azure 中 我目前的部署方式是这样的 在 web config 中 我将连接字符串从本地数据库 sdf 更改为 azur
  • 如何将除 Web API 之外的所有内容路由到 /index.html

    我一直在研究一个AngularJS项目 在 ASP NET MVC 内部使用 Web API 除非您尝试直接访问有角度的路由 URL 或刷新页面 否则它效果很好 我认为这将是我可以处理的事情 而不是胡闹服务器配置MVC的路由引擎 当前的We
  • MVC4:以电子邮件作为参数的 url 路由

    我有这个 url 在我的 VS Web 服务器上运行得非常好 http localhost 4454 cms account edituser email protected cdn cgi l email protection works
  • 如何为 asp.net MVC 5 配置 StructureMap

    我遇到以下错误 我的设置与 asp net mvc 4 类似 没有为此对象定义无参数构造函数 描述 安 当前网页执行期间发生未处理的异常 要求 请查看堆栈跟踪以获取有关的更多信息 错误及其在代码中的起源 异常详细信息 System Miss
  • 在运行时用Dagger添加Retrofit RequestInterceptor

    我正在使用匕首和改装 我用 Dagger 注入我的 Retrofit 服务 现在我想做一个授权请求来获取 accessToken 之后 我想使用请求拦截器来增强我的 api 模块 以便将此访问令牌用于将来的请求 我的想法是在收到访问令牌后使
  • 使用 Web API AuthorizeAttribute 角色的 Azure AD OAuth 客户端凭据授予流程

    Given 我们有 NET Web API 服务 它使用以下方式保护对控制器和操作的访问授权属性 https learn microsoft com en us dotnet api system web mvc authorizeattr
  • OAuth2 隐式流程 - IFrame 刷新身份

    我正在为隐式流开发 OAuth2 客户端 并正在实现基于 IFrame 的刷新 因为隐式流中没有刷新令牌 我所坚持的是试图找出将访问令牌传递回服务器的 标准 我是否通过 access token 查询字符串参数传回 或者在设置 IFrame
  • 创建包罗万象的路由

    我在网上找到了几个在 ASP NET MVC 中创建包罗万象的路由的示例 尤其是在 StackOverflow 上 但这似乎在 MVC4 中对我不起作用 public static void RegisterRoutes RouteColl
  • MVC4 捆绑:由于 css3 功能而缩小失败?

    我想使用 MVC4 捆绑和缩小 但我总是在未缩小的 css 文件中收到此错误消息作为注释 Minification failed Returning unminified contents 534 29 run time error CSS
  • 如何绕过 ASP.NET Web API 中发现多个操作的异常

    当试图找到以下问题的解决方案时 默认操作的 MVC Web Api 路由不起作用 https stackoverflow com questions 11724749 mvc web api route with default actio
  • ASP.NET MVC 粘贴到剪贴板

    我有一个 ASP NET MVC 4 应用程序 我想复制文本 从 PDF CTRL C 并将其作为参数粘贴到控制器的方法中 我的网络网格有一个带有 ActionLink 的列 grid Column format a href Url Ac

随机推荐

  • 从 DynamoDb 查询的 Python 脚本未提供所有项目

    我编写了以下 python 代码来从表中获取数据 但它没有按照我想要的方式获取所有项目 当我检查 DynamoDb 的 AWS 控制台页面时 我可以看到比从脚本中获得的条目多得多的条目 from future import print fu
  • 两个本体之间的映射

    我如何使用 owl sameas 来链接两个本体 如果我有本体A c rdf type owl Class 和本体B d rdf type owl Class 我想将两个本体与共享概念 c 和 d 联系起来 我读过有关 owl sameas
  • Flutter:webview_flutter 更新同一 webview 小部件中的 url

    嘿 我正在尝试创建一个屏幕 显示带有底部应用栏的网络视图 因此 您加载网络视图 当点击底部应用栏中的某个项目时 其他网站应该加载到同一个网络视图中 除了我最初解析的网站之外 我不知道如何打开另一个网站 我尝试使用 setState 更新网址
  • 处理kendo调度程序中的销毁事件

    我正在使用剑道调度程序 调度程序网格中添加了事件 当鼠标悬停在每个事件上时 右上角会出现一个小 x 即该事件的销毁事件 单击该事件时会显示一条警告消息 您确定要删除此事件吗 如果单击 是 它将继续并删除该事件 这是我的要求 正如您在上面看到
  • WSO2 身份服务器 - Oauth 2.0 - Java 签核示例

    我为 Oauth2 身份验证流程编写了一个基于 Java 的签核例程 令牌撤销 请参阅下面的代码实现 遵循手册中描述的 cURL 协议说明 here https docs wso2 com display IS500 OAuth Token
  • 下划线模板 - 更改标记标记

    开箱即用的下划线模板使用标记对于原始的 和用于 HTML 转义内容 我知道您可以使用以下方法更改标记 templateSettings interpolate g 但这与原始内容和转义内容有何关系 在我看来 你最终只能得到一种类型的标记 或
  • ScalaCheck 生成 BST

    我正在尝试使用 ScalaCheck 创建 BST 的 Gen 但是当我调用 sample 方法时 它给出了 java lang NullPointerException 我哪里错了 sealed trait Tree case class
  • 如何从

    我有一个严重的问题 我想从标签中提取内容 例如 div class main content div class sub content Sub content here div Main content here div 我期望的输出是
  • 机器人按键在 Linux 中不工作

    我多次使用 Robot 类 但在 Windows 中没有遇到任何问题 但这次我使用的是 Fedora 如果我尝试一下 keyPress KeyEvent VK WINDOWS 它不工作 如何在linux Fedora 中模拟按Windows
  • Ninject 通过城堡动态代理拦截具有非空构造函数的代理类

    我当前的大部分实现都基于此处提供的信息 Ninject 拦截任何具有特定属性的方法吗 https stackoverflow com questions 6386461 ninject intercept any method with c
  • x11 - 导入错误:没有名为“kivy.core.window.window_x11”的模块

    当我尝试在我的 kali linux 操作系统中使用 python 3 5 运行任何 kivy 程序时 然后我收到以下错误 程序 from kivy app import App from kivy lang import Builder
  • 为什么 Gradle 或 Maven 没有依赖版本锁定文件?

    最近 在阅读 NPM Yarn Paket Cargo 等包管理器时 我了解到依赖版本锁定文件的概念 我的理解是 它是一个列出所有直接和传递依赖项及其确切依赖项的文件 版本号 因此保证后续构建使用一组等效的依赖项 这似乎是一个理想的功能 因
  • 无需越狱 iPhone 即可访问 /var/mobile/Containers/Data/Application 中的文件

    程序在 iPhone 上的目录 var mobile Containers Data Application 中记录一些消息 有什么方法可以在不越狱 iPhone 的情况下访问此目录 如果没有 iPhone 上是否有任何目录可以让我在不越狱
  • MySQL 调试工具查询速度慢? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有哪些免费工具可以用来查找MySQL的慢查询 除了记录慢速查询之外 需要详细分析慢查询 谢谢 凯瑟尔 U
  • 多处理管理器出现 EOFError

    我有很多客户端通过 0MQ 连接到服务器 我有一个管理器队列 用于工作人员池与每台客户端计算机上的主进程进行通信 在一台拥有 250 个工作进程的客户端计算机上 我几乎立即看到一堆 EOFError 它们发生在执行 put 时 我预计大量的
  • 有没有办法在 Spark 中随机排列集合

    我需要用 2 2 10 9 行打乱文本文件 有没有办法将它加载到 Spark 中 然后并行地洗牌每个分区 对我来说 在分区范围内洗牌就足够了 然后将其溢出回文件 要仅在分区内进行洗牌 您可以执行以下操作 rdd mapPartitions
  • 这个校验和算法可以改进吗?

    我们有一个非常旧的 不受支持的程序 可以跨 SMB 共享复制文件 它有一个校验和算法来确定文件内容在复制之前是否已更改 该算法似乎很容易被愚弄 我们刚刚找到了一个示例 其中两个文件完全相同 除了单个 1 更改为 2 之外 返回相同的校验和
  • 无法使用 mailR 包通过 Outlook.com 发送电子邮件

    我想用 mailR 用于发送带有身份验证的电子邮件通知的包 这个包的支持者是 rJava 并使用 Java 设施 我注册了 Outlook com 帐户 这是代码 library mailR email lt send mail from
  • 读取 3 个字节作为整数

    如何读取 3 个字节的整数 struct module 是否提供类似的东西 我可以读取 3 个字节并添加一个额外的 x00 然后将其解释为 4 字节整数 但这似乎没有必要 struct 模块没有 3 字节整数的选项 所以我认为附加 x00
  • 从 oauth 身份验证获取电子邮件 (Microsoft)

    如何从微软帐户获取电子邮件 我正在执行以下操作 public ActionResult ExternalLoginCallback string returnUrl AuthenticationResult result OAuthWebS