public bool IsAccessGranted(IClient client, string[] scope, string resourceOwnerId) { //TODO: see why I'm passing in the scope AuthorizationGrant grant = TokenRepo.FindAuthorizationGrant(client.ClientId, resourceOwnerId); if (grant == null) { return(false); } if (!grant.IsApproved) { return(false); } bool scopeOk = true; foreach (string it in scope) { if (!grant.Scope.Split(' ').Contains(it)) { scopeOk = false; } break; } if (!scopeOk) { return(false); } return(true); // scope.Where(x => !grant.Scope.Contains(x.ToLower())).Count() == 0; }
public void ConsumeGrant(IAuthorizationGrant grant) { AuthorizationGrant gr = (AuthorizationGrant)grant; gr.IsUsed = true; TokenRepo.AddAuthorizationGrant(gr); }
public void Base64UriDecodeNoPaddingTest() { CollectionAssert.AreEqual(new byte[] { 0x11, 0x23 }, AuthorizationGrant.Base64UriDecodeNoPadding("ESM")); CollectionAssert.AreEqual(new byte[] { 0x1c, 0x4d, 0xe3 }, AuthorizationGrant.Base64UriDecodeNoPadding("HE3j")); CollectionAssert.AreEqual(new byte[] { 0x2e, 0xa8, 0x55, 0xb0, 0xbe }, AuthorizationGrant.Base64UriDecodeNoPadding("LqhVsL4")); CollectionAssert.AreEqual(new byte[] { 0x0c, 0x46, 0x46, 0x6f, 0x98, 0x03, 0x47, 0x2c, 0xd6, 0xbd, 0x2e, 0x28, 0x0e, 0x61, 0x30, 0x5f, 0xc1, 0x7e, 0x87, 0xc2, 0xdc, 0x76, 0x8e, 0x9f, 0x74, 0x18, 0x33, 0xb0, 0x8f, 0xfd, 0xf8, 0xda, }, AuthorizationGrant.Base64UriDecodeNoPadding("DEZGb5gDRyzWvS4oDmEwX8F-h8Lcdo6fdBgzsI_9-No")); }
public IAuthorizationGrant IssueAuthorizationGrant(IAuthorizationContext context) { AuthorizationGrant grant = new AuthorizationGrant(); Client client = ClientRepo.FindClient(context.Client.ClientId); grant.Client = client; grant.ResourceOwnerId = context.ResourceOwnerUsername; //grant.IsApproved = false; //grant.ExpiresIn = 120; // 2 minutes grant.Code = Guid.NewGuid().ToString(); grant.IssuedOn = SharpOAuth2.Provider.Utility.Epoch.ToEpoch(DateTime.Now); grant.Scope = string.Join(" ", context.Scope); TokenRepo.AddAuthorizationGrant(grant); return grant; }
public IAuthorizationGrant IssueAuthorizationGrant(IAuthorizationContext context) { AuthorizationGrant grant = new AuthorizationGrant(); Client client = ClientRepo.FindClient(context.Client.ClientId); grant.Client = client; grant.ResourceOwnerId = context.ResourceOwnerUsername; //grant.IsApproved = false; //grant.ExpiresIn = 120; // 2 minutes grant.Code = Guid.NewGuid().ToString(); grant.IssuedOn = SharpOAuth2.Provider.Utility.Epoch.ToEpoch(DateTime.Now); grant.Scope = string.Join(" ", context.Scope); TokenRepo.AddAuthorizationGrant(grant); return(grant); }
public void AddAuthorizationGrant(AuthorizationGrant grant) { Models.AuthorizationGrant authorizationGrant = new Models.AuthorizationGrant() { ClientId = Convert.ToInt32(grant.Client.ClientId), ExpiresIn = grant.ExpiresIn, IssuedOn = grant.IssuedOn, Scope = grant.Scope, Code = grant.Code, IsApproved = grant.IsApproved, IsUsed = grant.IsUsed, ResourceOwnerId = grant.ResourceOwnerId, }; using (Models.OAuthWebAPIContext context = new Models.OAuthWebAPIContext()) { context.AuthorizationGrants.Add(authorizationGrant); context.SaveChanges(); } }
/// <summary> /// Called when a server requests user authorization /// </summary> /// <param name="sender">Server of type <see cref="Server"/> requiring authorization</param> /// <param name="e">Authorization request event arguments</param> public void OnRequestAuthorization(object sender, RequestAuthorizationEventArgs e) { if (!(sender is Server authenticatingServer)) { return; } e.TokenOrigin = RequestAuthorizationEventArgs.TokenOriginType.None; e.AccessToken = null; lock (Properties.Settings.Default.AccessTokenCache) { if (e.SourcePolicy != RequestAuthorizationEventArgs.SourcePolicyType.ForceAuthorization) { var key = authenticatingServer.Base.AbsoluteUri; if (Properties.Settings.Default.AccessTokenCache.TryGetValue(key, out var accessToken)) { if (!e.ForceRefresh && DateTimeOffset.Now < accessToken.Expires) { e.TokenOrigin = RequestAuthorizationEventArgs.TokenOriginType.Saved; e.AccessToken = accessToken; return; } // Token refresh was explicitly requested or the token expired. Refresh it. if (accessToken is InvalidToken) { // Invalid token is not refreshable. Properties.Settings.Default.AccessTokenCache.Remove(key); } else { // Get API endpoints. (Not called from the UI thread or already cached by now. Otherwise it would need to be spawned as a background task to avoid deadlock.) var api = authenticatingServer.GetEndpoints(Window.Abort.Token); // Prepare web request. var request = Xml.Response.CreateRequest(api.TokenEndpoint); try { accessToken = accessToken.RefreshToken(request, null, Window.Abort.Token); // Update access token cache. Properties.Settings.Default.AccessTokenCache[key] = accessToken; // If we got here, return the token. e.TokenOrigin = RequestAuthorizationEventArgs.TokenOriginType.Refreshed; e.AccessToken = accessToken; return; } catch (AccessTokenException ex) { if (ex.ErrorCode == AccessTokenException.ErrorCodeType.InvalidGrant) { // The grant has been revoked. Drop the access token. Properties.Settings.Default.AccessTokenCache.Remove(key); } else { throw; } } } } } if (e.SourcePolicy != RequestAuthorizationEventArgs.SourcePolicyType.SavedOnly) { AuthorizationInProgress = new CancellationTokenSource(); Wizard.TryInvoke((Action)(() => { Wizard.TaskCount++; ReturnPage = Wizard.CurrentPage; Wizard.CurrentPage = this; })); try { // Get API endpoints. (Not called from the UI thread. Otherwise it would need to be spawned as a background task to avoid deadlock.) var api = authenticatingServer.GetEndpoints(Window.Abort.Token); // Prepare new authorization grant. AuthorizationGrant authorizationGrant = null; Uri callbackUri = null; var httpListener = new eduOAuth.HttpListener(IPAddress.Loopback, 0); httpListener.HttpCallback += (object _, HttpCallbackEventArgs eHTTPCallback) => { callbackUri = eHTTPCallback.Uri; AuthorizationInProgress.Cancel(); Wizard.TryInvoke((Action)(() => Wizard.CurrentPage = ReturnPage)); }; httpListener.HttpRequest += (object _, HttpRequestEventArgs eHTTPRequest) => { if (eHTTPRequest.Uri.AbsolutePath.ToLowerInvariant() == "/favicon.ico") { var res = System.Windows.Application.GetResourceStream(new Uri("pack://*****:*****@RETURN_TO@", HttpUtility.UrlEncode(authorizationUri.ToString())) .Replace("@ORG_ID@", HttpUtility.UrlEncode(srv.OrganizationId))); } // Trigger authorization. Process.Start(authorizationUri.ToString()); // Wait for a change: either callback is invoked, either user cancels. CancellationTokenSource.CreateLinkedTokenSource(AuthorizationInProgress.Token, Window.Abort.Token).Token.WaitHandle.WaitOne(); } finally { // Delay HTTP server shutdown allowing browser to finish loading content. new Thread(new ThreadStart(() => { Window.Abort.Token.WaitHandle.WaitOne(5 * 1000); httpListener.Stop(); })).Start(); } if (callbackUri == null) { throw new OperationCanceledException(); } // Get access token from authorization grant. var request = Xml.Response.CreateRequest(api.TokenEndpoint); e.AccessToken = authorizationGrant.ProcessResponse( HttpUtility.ParseQueryString(callbackUri.Query), request, null, Window.Abort.Token); Window.Abort.Token.ThrowIfCancellationRequested(); // Save access token to the cache. e.TokenOrigin = RequestAuthorizationEventArgs.TokenOriginType.Authorized; Properties.Settings.Default.AccessTokenCache[authenticatingServer.Base.AbsoluteUri] = e.AccessToken; } finally { Wizard.TryInvoke((Action)(() => Wizard.TaskCount--)); } } } }
public void AddAuthorizationGrant(AuthorizationGrant grant) { GrantRepo[grant.Code] = grant; }
public void AuthorizationGrantTest() { var ag = new AuthorizationGrant( new Uri("https://test.eduvpn.org/?param=1"), new Uri("org.eduvpn.app:/api/callback"), "org.eduvpn.app", new HashSet <string>() { "scope1", "scope2" }); var uriBuilder = new UriBuilder(ag.AuthorizationUri); Assert.AreEqual("https", uriBuilder.Scheme); Assert.AreEqual("test.eduvpn.org", uriBuilder.Host); Assert.AreEqual("/", uriBuilder.Path); var query = HttpUtility.ParseQueryString(uriBuilder.Query); Assert.AreEqual("1", query["param"]); Assert.AreEqual("code", query["response_type"]); Assert.AreEqual("org.eduvpn.app", query["client_id"]); Assert.AreEqual("org.eduvpn.app:/api/callback", query["redirect_uri"]); CollectionAssert.AreEqual(new List <string>() { "scope1", "scope2" }, query["scope"].Split(null)); Assert.IsTrue(AuthorizationGrant.Base64UriDecodeNoPadding(query["state"]).Length > 0); Assert.AreEqual("S256", query["code_challenge_method"]); Assert.IsTrue(AuthorizationGrant.Base64UriDecodeNoPadding(query["code_challenge"]).Length > 0); var request = new Mock <HttpWebRequest>(); request.Setup(obj => obj.RequestUri).Returns(new Uri("https://demo.eduvpn.nl/portal/oauth.php/token")); request.SetupSet(obj => obj.Method = "POST"); request.SetupProperty(obj => obj.Credentials); request.SetupProperty(obj => obj.PreAuthenticate, false); request.SetupSet(obj => obj.ContentType = "application/x-www-form-urlencoded"); request.SetupProperty(obj => obj.ContentLength); var request_buffer = new byte[1048576]; request.Setup(obj => obj.GetRequestStream()).Returns(new MemoryStream(request_buffer, true)); var response = new Mock <HttpWebResponse>(); response.Setup(obj => obj.GetResponseStream()).Returns(new MemoryStream(Encoding.UTF8.GetBytes(Global.AccessTokenJSON))); response.SetupGet(obj => obj.StatusCode).Returns(HttpStatusCode.OK); request.Setup(obj => obj.GetResponse()).Returns(response.Object); AccessToken token1 = new BearerToken(Global.AccessTokenObj, DateTimeOffset.Now), token2 = ag.ProcessResponse(new NameValueCollection() { { "state", query["state"] }, { "code", "1234567890" } }, request.Object, new NetworkCredential("", "password").SecurePassword); var request_param = HttpUtility.ParseQueryString(Encoding.ASCII.GetString(request_buffer, 0, (int)request.Object.ContentLength)); Assert.AreEqual("authorization_code", request_param["grant_type"]); Assert.IsNotNull(request_param["code"]); Assert.AreEqual(ag.RedirectEndpoint, request_param["redirect_uri"]); Assert.AreEqual(ag.ClientId, request_param["client_id"]); Assert.IsNotNull(request_param["code_verifier"]); Assert.AreEqual(token1, token2); Assert.IsTrue((token1.Authorized - token2.Authorized).TotalSeconds < 60); Assert.IsTrue((token1.Expires - token2.Expires).TotalSeconds < 60); Assert.IsTrue(token2.Scope != null); Assert.IsTrue(token1.Scope.SetEquals(token2.Scope)); Assert.ThrowsException <eduJSON.MissingParameterException>(() => ag.ProcessResponse(new NameValueCollection() { { "code", "1234567890" } }, request.Object)); Assert.ThrowsException <eduJSON.MissingParameterException>(() => ag.ProcessResponse(new NameValueCollection() { { "state", query["state"] } }, request.Object)); Assert.ThrowsException <InvalidStateException>(() => ag.ProcessResponse(new NameValueCollection() { { "state", AuthorizationGrant.Base64UrlEncodeNoPadding(new byte[] { 0x01, 0x02, 0x03 }) }, { "code", "1234567890" } }, request.Object)); Assert.ThrowsException <AuthorizationGrantException>(() => ag.ProcessResponse(new NameValueCollection() { { "state", query["state"] }, { "error", "error" }, { "code", "1234567890" } }, request.Object)); Assert.ThrowsException <eduJSON.MissingParameterException>(() => ag.ProcessResponse(new NameValueCollection() { { "state", query["state"] } }, request.Object)); }
/// <summary> /// Constructs event arguments /// </summary> /// <param name="instance">Authenticating instance</param> /// <param name="authorization_grant">Authorization grant</param> public RequestInstanceAuthorizationEventArgs(Instance instance, AuthorizationGrant authorization_grant) { Instance = instance; AuthorizationGrant = authorization_grant; }