/// <summary> /// Reads authorization code from current session. /// </summary> public static bool ReadAuthCodeRequest( HttpContextBase webContext, out string code, out string state, out string requestTs, out LiveAuthException error) { Debug.Assert(webContext != null); NameValueCollection queryString = webContext.Request.QueryString; code = queryString[AuthConstants.Code]; bool isCodeRequest = !string.IsNullOrEmpty(code); string clientState = queryString[AuthConstants.ClientState]; IDictionary <string, string> states = LiveAuthUtility.DecodeAppRequestStates(clientState); state = states.ContainsKey(AuthConstants.AppState) ? states[AuthConstants.AppState] : null; requestTs = states.ContainsKey(AuthConstants.ClientRequestTs) ? states[AuthConstants.ClientRequestTs] : null; string errorCode = queryString[AuthConstants.Error]; string errorDescription = queryString[AuthConstants.ErrorDescription]; error = string.IsNullOrEmpty(errorCode) ? null : new LiveAuthException(errorCode, errorDescription, state); return(isCodeRequest); }
/// <summary> /// An async method to exhange authorization code for auth tokens with the auth server. /// </summary> public static Task <LiveLoginResult> ExchangeCodeForTokenAsync(string clientId, string clientSecret, string redirectUrl, string authorizationCode) { Debug.Assert(!string.IsNullOrEmpty(clientId)); Debug.Assert(!string.IsNullOrEmpty(redirectUrl)); Debug.Assert(!string.IsNullOrEmpty(authorizationCode)); string postContent = LiveAuthUtility.BuildCodeTokenExchangePostContent(clientId, clientSecret, redirectUrl, authorizationCode); return(RequestAccessTokenAsync(postContent)); }
/// <summary> /// An async method to get auth tokens using refresh token. /// </summary> public static Task <LiveLoginResult> RefreshTokenAsync( string clientId, string clientSecret, string redirectUrl, string refreshToken, IEnumerable <string> scopes) { Debug.Assert(!string.IsNullOrEmpty(clientId)); Debug.Assert(!string.IsNullOrEmpty(redirectUrl)); Debug.Assert(!string.IsNullOrEmpty(refreshToken)); string postContent = LiveAuthUtility.BuildRefreshTokenPostContent(clientId, clientSecret, redirectUrl, refreshToken, scopes); return(RequestAccessTokenAsync(postContent)); }
private void ExchangeCodeForToken(string authorizationCode) { Task <LiveLoginResult> task = LiveAuthRequestUtility.ExchangeCodeForTokenAsync( this.clientId, null, LiveAuthUtility.BuildDesktopRedirectUrl(), authorizationCode); task.ContinueWith((Task <LiveLoginResult> t) => { this.OnExchangeCodeCompleted(t.Result); }); }
private LiveLoginResult ValidateSessionInitScopes(LiveLoginResult loginResult) { if (loginResult.Session != null && this.initScopes != null) { if (!LiveAuthUtility.IsSubsetOfScopeRange(this.initScopes, loginResult.Session.Scopes)) { loginResult = new LiveLoginResult(LiveConnectSessionStatus.NotConnected, null); } this.initScopes = null; } return(loginResult); }
/// <summary> /// Generates a consent URL that includes a set of provided parameters. /// </summary> /// <param name="scopes">A list of scope values that the user will need to authorize.</param> /// <param name="options">A table of optional authorization parameters to be encoded into the URL.</param> /// <returns>The generated login URL value.</returns> public string GetLoginUrl(IEnumerable <string> scopes, IDictionary <string, string> options) { LiveUtility.ValidateNotEmptyStringEnumeratorArguement(scopes, "scopes"); string locale = null; string state = null; DisplayType display = DisplayType.WinDesktop; ThemeType theme = ThemeType.Win7; string redirectUrl = LiveAuthUtility.BuildDesktopRedirectUrl(); if (options != null) { if (options.ContainsKey(AuthConstants.Locale)) { locale = options[AuthConstants.Locale]; } if (options.ContainsKey(AuthConstants.ClientState)) { state = options[AuthConstants.ClientState]; } if (options.ContainsKey(AuthConstants.Display)) { string displayStr = options[AuthConstants.Display]; if (!Enum.TryParse <DisplayType>(displayStr, true, out display)) { throw new ArgumentException(ErrorText.ParameterInvalidDisplayValue, "display"); } } if (options.ContainsKey(AuthConstants.Theme)) { string themeStr = options[AuthConstants.Theme]; if (!Enum.TryParse <ThemeType>(themeStr, true, out theme)) { throw new ArgumentException(ErrorText.ParameterInvalidDisplayValue, "theme"); } } } if (locale == null) { locale = CultureInfo.CurrentUICulture.ToString(); } return(this.authClient.GetLoginUrl(scopes, redirectUrl, display, theme, locale, state)); }
//private static Task<LiveLoginResult> RequestAccessTokenAsync(string postContent) //{ // Task<LiveLoginResult> task = Task.Factory.StartNew(() => // { // return RequestAccessToken(postContent); // }); // return task; //} private static async Task <LiveLoginResult> RequestAccessTokenAsync(string postContent) { string url = LiveAuthUtility.BuildTokenUrl(); HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; HttpWebResponse response = null; LiveLoginResult loginResult = null; request.Method = ApiMethod.Post.ToString().ToUpperInvariant(); request.ContentType = TokenRequestContentType; try { var requestStream = await request.GetRequestStreamAsync(); using (StreamWriter writer = new StreamWriter(requestStream)) { writer.Write(postContent); } response = await request.GetResponseAsync() as HttpWebResponse; loginResult = ReadResponse(response); } catch (WebException e) { response = e.Response as HttpWebResponse; loginResult = ReadResponse(response); } catch (IOException ioe) { loginResult = new LiveLoginResult(new LiveAuthException(AuthErrorCodes.ClientError, ioe.Message)); } finally { if (response != null) { //response.Close(); response.Dispose(); } } if (loginResult == null) { loginResult = new LiveLoginResult(new LiveAuthException(AuthErrorCodes.ClientError, ErrorText.RetrieveTokenError)); } return(loginResult); }
/// <summary> /// Exchange authentication code for access token. /// </summary> /// <param name="context">The HttpContextBase instance</param> /// <param name="redirectUri">The redirect URL of the app.</param> /// <returns>An async Task instance.</returns> public Task <LiveLoginResult> ExchangeAuthCodeAsync( HttpContextBase context, string redirectUrl) { LiveUtility.ValidateNotNullParameter(context, "context"); if (string.IsNullOrWhiteSpace(redirectUrl)) { redirectUrl = LiveAuthUtility.GetCurrentRedirectUrl(context.Request.Url); } else { LiveUtility.ValidateUrl(redirectUrl, "redirectUrl"); } return(this.authClient.ExchangeAuthCodeAsync(redirectUrl, context)); }
/// <summary> /// Initializes the LiveAuthClient instance for the current user. /// If an authorization code is present, it will send a request to the auth server to exchange the token. /// If there is an auth session in current context, it will retrieve the current auth session. /// If the current session is expired or the current request url indicates (refresh=1) to get a new token, /// it will try to request a new access token using refresh token that will need to be provided through /// IRefreshTokenHandler.RetrieveRefreshTokenAsync() method. /// Any updated session state will be saved in the auth session cookie. /// </summary> /// <param name="context">The HttpContextBase instance of current request.</param> /// <param name="redirectUrl">The redirect URL of the app. This must match exactly the Url that is used to /// generate the login Url via LiveAuthClient.GetLoginUrl</param> /// <param name="scopes">A list of scopes to validate whether the user has consented. If the available session /// does not satisfy the specified scopes, NotConnected status will be returned. However, the developer still /// can find the available session throw the Session property.</param> /// <returns>An async Task instance</returns> public Task <LiveLoginResult> InitializeWebSessionAsync( HttpContextBase context, string redirectUrl, IEnumerable <string> scopes) { LiveUtility.ValidateNotNullParameter(context, "context"); if (string.IsNullOrWhiteSpace(redirectUrl)) { redirectUrl = LiveAuthUtility.GetCurrentRedirectUrl(context.Request.Url); } else { LiveUtility.ValidateUrl(redirectUrl, "redirectUrl"); } return(this.authClient.InitializeWebSessionAsync(redirectUrl, context, scopes)); }
private void RefreshToken(Action <LiveLoginResult> completionCallback) { if (this.refreshTokenInfo != null) { LiveAuthRequestUtility.RefreshTokenAsync( this.clientId, null, LiveAuthUtility.BuildDesktopRedirectUrl(), this.refreshTokenInfo.RefreshToken, null /*scopes*/ ).ContinueWith(t => { this.OnRefreshTokenCompleted(t.Result, completionCallback); }); } else { LiveLoginResult result = new LiveLoginResult(LiveConnectSessionStatus.Unknown, null); this.OnRefreshTokenCompleted(result, completionCallback); } }
/// <summary> /// Creates a LiveConnectSession object based on the parsed response. /// </summary> private static LiveConnectSession CreateSession(IDictionary <string, object> result) { var session = new LiveConnectSession(); Debug.Assert(result.ContainsKey(AuthConstants.AccessToken)); if (result.ContainsKey(AuthConstants.AccessToken)) { session.AccessToken = result[AuthConstants.AccessToken] as string; if (result.ContainsKey(AuthConstants.AuthenticationToken)) { session.AuthenticationToken = result[AuthConstants.AuthenticationToken] as string; } if (result.ContainsKey(AuthConstants.ExpiresIn)) { if (result[AuthConstants.ExpiresIn] is string) { session.Expires = CalculateExpiration(result[AuthConstants.ExpiresIn] as string); } else { session.Expires = DateTimeOffset.UtcNow.AddSeconds((int)result[AuthConstants.ExpiresIn]); } } if (result.ContainsKey(AuthConstants.Scope)) { session.Scopes = LiveAuthUtility.ParseScopeString(result[AuthConstants.Scope] as string); } if (result.ContainsKey(AuthConstants.RefreshToken)) { session.RefreshToken = result[AuthConstants.RefreshToken] as string; } } return(session); }
/// <summary> /// Reads current user session. /// </summary> public static LiveLoginResult GetUserLoginStatus(HttpContextBase webContext) { Debug.Assert(webContext != null); HttpCookie cookie = webContext.Request.Cookies[AuthCookie]; LiveConnectSession session = null; LiveConnectSessionStatus status = LiveConnectSessionStatus.Unknown; if (cookie != null && cookie.Values != null) { string accessToken = cookie[AuthConstants.AccessToken]; if (!string.IsNullOrEmpty(accessToken)) { session = new LiveConnectSession(); session.AccessToken = UrlDataDecode(accessToken); session.AuthenticationToken = UrlDataDecode(cookie[AuthConstants.AuthenticationToken]); session.RefreshToken = UrlDataDecode(cookie[AuthConstants.RefreshToken]); session.Scopes = LiveAuthUtility.ParseScopeString(UrlDataDecode(cookie[AuthConstants.Scope])); session.Expires = LiveAuthWebUtility.ParseExpiresValue(UrlDataDecode(cookie[AuthConstants.Expires])); status = session.IsValid ? LiveConnectSessionStatus.Connected : LiveConnectSessionStatus.Expired; } else { // If we previously recorded NotConnected, take that value. // Ignore other values that may be set by JS library. LiveConnectSessionStatus statusFromCookie; if (Enum.TryParse <LiveConnectSessionStatus>(cookie[AuthConstants.Status], true /*ignore case*/, out statusFromCookie)) { if (statusFromCookie == LiveConnectSessionStatus.NotConnected) { status = statusFromCookie; } } } } return(new LiveLoginResult(status, session)); }
/// <summary> /// Check if current session has a token request. /// </summary> public static bool ReadRefreshTokenRequest( HttpContextBase webContext, out string clientId, out IEnumerable <string> scopes) { clientId = null; scopes = null; bool isTokenRequest = false; if (webContext != null) { NameValueCollection queryString = webContext.Request.QueryString; string requestToken = queryString[AuthConstants.ResponseType]; isTokenRequest = (requestToken == AuthConstants.Token); if (isTokenRequest) { clientId = queryString[AuthConstants.ClientId]; // If this is sent by the client library, the token response should honor the scope parameter. scopes = LiveAuthUtility.ParseScopeString(queryString[AuthConstants.Scope]); } } return(isTokenRequest); }
/// <summary> /// Writes the user current session. /// </summary> public static void UpdateUserSession(HttpContextBase context, LiveLoginResult loginResult, string requestTs) { if (context == null) { return; } Debug.Assert(loginResult != null); Dictionary <string, string> cookieValues = new Dictionary <string, string>(); HttpCookie cookie = context.Request.Cookies[AuthCookie]; HttpCookie newCookie = new HttpCookie(AuthCookie); newCookie.Path = "/"; string host = context.Request.Headers["Host"]; newCookie.Domain = host.Split(':')[0]; if (cookie != null && cookie.Values != null) { foreach (string key in cookie.Values.AllKeys) { newCookie.Values[key] = cookie[key]; } } LiveConnectSession session = loginResult.Session; if (session != null) { newCookie.Values[AuthConstants.AccessToken] = Uri.EscapeDataString(session.AccessToken); newCookie.Values[AuthConstants.AuthenticationToken] = Uri.EscapeDataString(session.AuthenticationToken); newCookie.Values[AuthConstants.Scope] = Uri.EscapeDataString(LiveAuthUtility.BuildScopeString(session.Scopes)); newCookie.Values[AuthConstants.ExpiresIn] = Uri.EscapeDataString(LiveAuthWebUtility.GetExpiresInString(session.Expires)); newCookie.Values[AuthConstants.Expires] = Uri.EscapeDataString(LiveAuthWebUtility.GetExpiresString(session.Expires)); } LiveConnectSessionStatus status; if (!string.IsNullOrEmpty(newCookie[AuthConstants.AccessToken])) { // We have an access token, so it is connected, regardless expired or not // since it is handled after loading the session in both Asp.Net and JS library. status = LiveConnectSessionStatus.Connected; } else { status = loginResult.Status; if (loginResult.Status == LiveConnectSessionStatus.Unknown) { // If we recorded NotConnected previously, keep it. LiveConnectSessionStatus statusFromCookie; if (Enum.TryParse <LiveConnectSessionStatus>( newCookie[AuthConstants.Status], true /*ignore case*/, out statusFromCookie)) { if (statusFromCookie == LiveConnectSessionStatus.NotConnected) { status = statusFromCookie; } } } } newCookie.Values[AuthConstants.Status] = GetStatusString(status); // Needs to write error to inform the JS library. LiveAuthException authError = loginResult.Error as LiveAuthException; if (authError != null) { newCookie.Values[AuthConstants.Error] = Uri.EscapeDataString(authError.ErrorCode); newCookie.Values[AuthConstants.ErrorDescription] = HttpUtility.UrlPathEncode(authError.Message); } else if (status != LiveConnectSessionStatus.Connected) { newCookie.Values[AuthConstants.Error] = Uri.EscapeDataString(AuthErrorCodes.AccessDenied); newCookie.Values[AuthConstants.ErrorDescription] = HttpUtility.UrlPathEncode("Cannot retrieve access token."); } if (!string.IsNullOrEmpty(requestTs)) { newCookie.Values[AuthConstants.ClientRequestTs] = requestTs; } context.Response.Cookies.Add(newCookie); }
/// <summary> /// Gets the logout URL. /// </summary> /// <returns>The logout URL.</returns> public string GetLogoutUrl() { return(LiveAuthUtility.BuildLogoutUrl()); }
/// <summary> /// Generates a logout URL. /// </summary> public string GetLogoutUrl(string redirectUrl) { return(LiveAuthUtility.BuildLogoutUrl(this.clientId, redirectUrl)); }
/// <summary> /// Generates a consent URL that includes a set of provided parameters. /// </summary> public string GetLoginUrl(IEnumerable <string> scopes, string redirectUrl, DisplayType display, string locale, string state) { return(LiveAuthUtility.BuildAuthorizeUrl(this.clientId, redirectUrl, scopes, ResponseType.Code, display, ThemeType.None, locale, state)); }