public async Task missing_identity_token_on_token_response_should_fail() { var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, //{ "id_token", "id_token" }, { "refresh_token", "refresh_token" } }; _options.BackchannelHandler = new NetworkHandler(JsonConvert.SerializeObject(tokenResponse), HttpStatusCode.OK); var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeTrue(); result.Error.Should().Be("Error validating token response: Identity token is missing on token response."); }
public async Task malformed_identity_token_on_token_response_should_fail() { var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", "id_token" }, { "refresh_token", "refresh_token" } }; _options.BackchannelHandler = new NetworkHandler(JsonConvert.SerializeObject(tokenResponse), HttpStatusCode.OK); var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeTrue(); result.Error.Should().StartWith("Error validating token response: Error validating identity token: System.ArgumentException: IDX10709: JWT is not well formed"); }
public async Task Malformed_identity_token_on_token_response_should_fail() { var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", "id_token" }, { "refresh_token", "refresh_token" } }; _options.BackchannelHandler = new NetworkHandler(JsonSerializer.Serialize(tokenResponse), HttpStatusCode.OK); var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeTrue(); result.Error.Should().Contain("invalid_jwt"); }
public async Task no_keyset_for_identity_token_should_fail() { var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", Crypto.UntrustedIdentityToken }, { "refresh_token", "refresh_token" } }; _options.BackchannelHandler = new NetworkHandler(JsonConvert.SerializeObject(tokenResponse), HttpStatusCode.OK); var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeTrue(); result.Error.Should().StartWith("Error validating token response: Error validating identity token: Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10500: Signature validation failed. No security keys were provided to validate the signature"); }
public async Task No_keyset_for_identity_token_should_fail() { var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", Crypto.UntrustedIdentityToken }, { "refresh_token", "refresh_token" } }; _options.BackchannelHandler = new NetworkHandler(JsonConvert.SerializeObject(tokenResponse), HttpStatusCode.OK); var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeTrue(); result.Error.Should().Contain("IDX10501"); }
public async Task invalid_nonce_should_fail() { var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var key = Crypto.CreateKey(); _options.ProviderInformation.KeySet = Crypto.CreateKeySet(key); var frontChannelJwt = Crypto.CreateJwt(key, "https://authority", "client", new Claim("sub", "123"), new Claim("nonce", "invalid"), new Claim("c_hash", Crypto.HashData("code"))); var url = $"?state={state.State}&code=code&id_token={frontChannelJwt}"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeTrue(); result.Error.Should().Be("Invalid nonce."); }
public async Task Extra_parameters_on_backchannel_should_be_sent() { var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var idToken = Crypto.CreateJwt(null, "https://authority", "client", new Claim("at_hash", Crypto.HashData("token")), new Claim("sub", "123")); var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", idToken }, { "refresh_token", "refresh_token" } }; var handler = new NetworkHandler(JsonSerializer.Serialize(tokenResponse), HttpStatusCode.OK); _options.BackchannelHandler = handler; var backChannel = new Parameters { { "foo", "foo" }, { "bar", "bar" } }; var result = await client.ProcessResponseAsync(url, state, backChannel); result.IsError.Should().BeFalse(); result.AccessToken.Should().Be("token"); result.IdentityToken.Should().NotBeNull(); result.User.Should().NotBeNull(); var body = handler.Body; body.Should().Contain("foo=foo"); body.Should().Contain("bar=bar"); }
public async Task untrusted_identity_token_should_fail() { var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", Crypto.UntrustedIdentityToken }, { "refresh_token", "refresh_token" } }; _options.ProviderInformation.KeySet = Crypto.CreateKeySet(Crypto.CreateKey()); _options.BackchannelHandler = new NetworkHandler(JsonConvert.SerializeObject(tokenResponse), HttpStatusCode.OK); var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeTrue(); result.Error.Should().StartWith("Error validating token response: Error validating identity token: Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match 'kid'"); }
private async void PrepareClient() { var redirectUri = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().OriginalString; // Create options for endpoint discovery var options = new OidcClientOptions() { Authority = "https://demo.identityserver.io", ClientId = "interactive.confidential", ClientSecret = "secret", Scope = "openid profile email api offline_access", RedirectUri = redirectUri, PostLogoutRedirectUri = redirectUri, ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect, Flow = OidcClientOptions.AuthenticationFlow.AuthorizationCode }; // Create the client. In production application, this is often created and stored // directly in the Application class. _oidcClient = new OidcClient(options); // Invoke Discovery and prepare a request state, containing the nonce. // This is done here to ensure the discovery mecanism is done before // the user clicks on the SignIn button. Since the opening of a web window // should be done during the handling of a user interaction (here it's the button click), // it will be too late to reach the discovery endpoint. // Not doing this could trigger popup blockers mechanisms in browsers. _loginState = await _oidcClient.PrepareLoginAsync(); btnSignin.IsEnabled = true; resultTxt.Text = "Login URI correct"; // Same for logout url. _logoutUrl = new Uri(await _oidcClient.PrepareLogoutAsync(new LogoutRequest())); btnSignout.IsEnabled = true; resultTxt.Text = $"Initialization completed.\nStart={_loginState.StartUrl}\nCallback={_loginState.RedirectUri}\nLogout={_logoutUrl}"; }
public async Task At_hash_policy_should_be_enforced(bool atHashRequired) { var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&nonce={state.Nonce}&code=bar"; var key = Crypto.CreateKey(); var idToken = Crypto.CreateJwt(key, "https://authority", "client", new Claim("sub", "123"), new Claim("nonce", state.Nonce)); var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", idToken }, { "refresh_token", "refresh_token" } }; _options.ProviderInformation.KeySet = Crypto.CreateKeySet(key); _options.BackchannelHandler = new NetworkHandler(JsonSerializer.Serialize(tokenResponse), HttpStatusCode.OK); _options.Policy.RequireAccessTokenHash = atHashRequired; var result = await client.ProcessResponseAsync(url, state); if (atHashRequired) { result.IsError.Should().BeTrue(); result.Error.Should().Be("Error validating token response: at_hash is missing."); } else { result.IsError.Should().BeFalse(); result.AccessToken.Should().Be("token"); result.IdentityToken.Should().NotBeNull(); result.User.Should().NotBeNull(); } }
public async Task Untrusted_identity_token_should_fail() { var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", Crypto.UntrustedIdentityToken }, { "refresh_token", "refresh_token" } }; _options.ProviderInformation.KeySet = Crypto.CreateKeySet(Crypto.CreateKey()); _options.BackchannelHandler = new NetworkHandler(JsonSerializer.Serialize(tokenResponse), HttpStatusCode.OK); var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeTrue(); result.Error.Should().Contain("invalid_signature"); }
public async Task Sending_authorization_header_should_succeed() { _options.ClientSecret = "secret"; _options.TokenClientCredentialStyle = Client.ClientCredentialStyle.AuthorizationHeader; var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&nonce={state.Nonce}&code=bar"; var key = Crypto.CreateKey(); var idToken = Crypto.CreateJwt(key, "https://authority", "client", new Claim("at_hash", Crypto.HashData("token")), new Claim("sub", "123"), new Claim("nonce", state.Nonce)); var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", idToken }, { "refresh_token", "refresh_token" } }; _options.ProviderInformation.KeySet = Crypto.CreateKeySet(key); var backChannelHandler = new NetworkHandler(JsonSerializer.Serialize(tokenResponse), HttpStatusCode.OK); _options.BackchannelHandler = backChannelHandler; var result = await client.ProcessResponseAsync(url, state); var request = backChannelHandler.Request; request.Headers.Authorization.Should().NotBeNull(); request.Headers.Authorization.Scheme.Should().Be("Basic"); request.Headers.Authorization.Parameter.Should() .Be(BasicAuthenticationOAuthHeaderValue.EncodeCredential("client", "secret")); }
public async Task Valid_response_with_missing_signature_should_succeed() { _options.Policy.RequireIdentityTokenSignature = false; var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&nonce={state.Nonce}&code=bar"; var key = Crypto.CreateKey(); var idToken = Crypto.CreateJwt(null, "https://authority", "client", new Claim("at_hash", Crypto.HashData("token")), new Claim("sub", "123"), new Claim("nonce", state.Nonce)); var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", idToken }, { "refresh_token", "refresh_token" } }; _options.ProviderInformation.KeySet = Crypto.CreateKeySet(key); _options.BackchannelHandler = new NetworkHandler(JsonSerializer.Serialize(tokenResponse), HttpStatusCode.OK); var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeFalse(); result.AccessToken.Should().Be("token"); result.IdentityToken.Should().NotBeNull(); result.User.Should().NotBeNull(); result.User.Claims.Count().Should().Be(1); result.User.Claims.First().Type.Should().Be("sub"); result.User.Claims.First().Value.Should().Be("123"); }
public async Task Valid_response_should_succeed() { var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var key = Crypto.CreateKey(); var frontChannelJwt = Crypto.CreateJwt(key, "https://authority", "client", new Claim("sub", "123"), new Claim("nonce", state.Nonce), new Claim("c_hash", Crypto.HashData("code"))); var url = $"?state={state.State}&nonce={state.Nonce}&code=code&id_token={frontChannelJwt}"; var backChannelJwt = Crypto.CreateJwt(key, "https://authority", "client", new Claim("at_hash", Crypto.HashData("token")), new Claim("sub", "123"), new Claim("nonce", state.Nonce)); var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", backChannelJwt }, { "refresh_token", "refresh_token" } }; _options.ProviderInformation.KeySet = Crypto.CreateKeySet(key); _options.BackchannelHandler = new NetworkHandler(JsonConvert.SerializeObject(tokenResponse), HttpStatusCode.OK); var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeFalse(); result.AccessToken.Should().Be("token"); result.IdentityToken.Should().NotBeNull(); result.User.Should().NotBeNull(); result.TokenResponse.Should().NotBeNull(); }
public async Task Sending_client_credentials_in_body_should_succeed() { _options.ClientSecret = "secret"; _options.TokenClientCredentialStyle = Client.ClientCredentialStyle.PostBody; var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&nonce={state.Nonce}&code=bar"; var key = Crypto.CreateKey(); var idToken = Crypto.CreateJwt(key, "https://authority", "client", new Claim("at_hash", Crypto.HashData("token")), new Claim("sub", "123"), new Claim("nonce", state.Nonce)); var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", idToken }, { "refresh_token", "refresh_token" } }; _options.ProviderInformation.KeySet = Crypto.CreateKeySet(key); var backChannelHandler = new NetworkHandler(JsonConvert.SerializeObject(tokenResponse), HttpStatusCode.OK); _options.BackchannelHandler = backChannelHandler; var result = await client.ProcessResponseAsync(url, state); var fields = QueryHelpers.ParseQuery(backChannelHandler.Body); fields["client_id"].First().Should().Be("client"); fields["client_secret"].First().Should().Be("secret"); }
public async Task No_identity_token_on_token_response_and_no_profile_loading_should_succeed() { var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "refresh_token", "refresh_token" } }; _options.BackchannelHandler = new NetworkHandler(JsonConvert.SerializeObject(tokenResponse), HttpStatusCode.OK); var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&code=bar"; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeFalse(); result.AccessToken.Should().Be("token"); result.IdentityToken.Should().BeNull(); result.User.Should().NotBeNull(); result.User.Claims.Count().Should().Be(0); }
public async Task Valid_response_without_id_token_should_succeed() { _options.Scope = "api"; var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&nonce={state.Nonce}&code=bar"; var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "refresh_token", "refresh_token" } }; _options.BackchannelHandler = new NetworkHandler(JsonSerializer.Serialize(tokenResponse), HttpStatusCode.OK); var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeFalse(); result.AccessToken.Should().Be("token"); result.IdentityToken.Should().BeNull(); result.User.Identity.IsAuthenticated.Should().BeFalse(); }
private static async Task <string> SignIn() { // create a redirect URI using an available port on the loopback address. const string redirectUri = SampleUrls.ConsoleAppCallback; Console.WriteLine("redirect URI: " + redirectUri); // create an HttpListener to listen for requests on that redirect URI. var oidcRedirectListener = new HttpListener(); oidcRedirectListener.Prefixes.Add(redirectUri); Console.WriteLine("Listening.."); oidcRedirectListener.Start(); try { var options = new OidcClientOptions { Authority = SampleUrls.SecurityTokenService, ClientId = Clients.ConsoleApp, ClientSecret = Secrets.ConsoleApp, Scope = $"openid profile {SampleScopes.TestApi}", RedirectUri = redirectUri }; var client = new OidcClient(options); AuthorizeState state = await client.PrepareLoginAsync(); Console.WriteLine($"Start URL: {state.StartUrl}"); // open system browser to start authentication OpenBrowser(state.StartUrl); // wait for the authorization response. HttpListenerContext oidcRedirectListenerContext = await oidcRedirectListener.GetContextAsync(); string formData = GetRequestPostData(oidcRedirectListenerContext.Request); // Brings the Console to Focus. //BringConsoleToFront(); // todo: this failed in macos, seems to be windows-only implementation, investigate, commenting out for now // sends an HTTP response to the browser. HttpListenerResponse response = oidcRedirectListenerContext.Response; string responseString = $"<html><head><meta http-equiv='refresh' content='10;url={SampleUrls.SecurityTokenService}'></head><body>Please return to the app.</body></html>"; byte[] buffer = Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; Stream responseOutput = response.OutputStream; await responseOutput.WriteAsync(buffer, 0, buffer.Length); responseOutput.Close(); Console.WriteLine($"Form Data: {formData}"); Console.WriteLine(); Console.WriteLine("going to process response, press any key to continue..."); Console.ReadKey(); LoginResult result = await client.ProcessResponseAsync(formData, state); if (result.IsError) { Console.WriteLine("\n\nError:\n{0}", result.Error); return(null); } Console.WriteLine("\n\nClaims:"); foreach (Claim claim in result.User.Claims) { Console.WriteLine(" [{0}]: [{1}]", claim.Type, claim.Value); } Console.WriteLine(); Console.WriteLine("Access token:\n\n{0}\n", result.AccessToken); if (!string.IsNullOrWhiteSpace(result.RefreshToken)) { Console.WriteLine("Refresh token:\n\n{0}\n", result.RefreshToken); } return(result.AccessToken); } finally { oidcRedirectListener.Stop(); } }
private async Task SignIn() { // create a redirect URI using the custom redirect uri string redirectUri = string.Format(CustomUriScheme + "://callback"); Console.WriteLine("redirect URI: " + redirectUri); var options = new OidcClientOptions { Authority = Constants.Authority, ClientId = "winconsole", Scope = "openid profile api1", RedirectUri = redirectUri, }; var serilog = new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.FromLogContext() .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}{Exception}{NewLine}") .CreateLogger(); options.LoggerFactory.AddSerilog(serilog); var client = new OidcClient(options); var state = await client.PrepareLoginAsync(); Console.WriteLine($"Start URL: {state.StartUrl}"); var callbackManager = new CallbackManager(state.State); // open system browser to start authentication Process.Start(state.StartUrl); Console.WriteLine("Running callback manager"); var response = await callbackManager.RunServer(); Console.WriteLine($"Response from authorize endpoint: {response}"); // Brings the Console to Focus. BringConsoleToFront(); var result = await client.ProcessResponseAsync(response, state); BringConsoleToFront(); if (result.IsError) { Console.WriteLine("\n\nError:\n{0}", result.Error); } else { Console.WriteLine("\n\nClaims:"); foreach (var claim in result.User.Claims) { Console.WriteLine("{0}: {1}", claim.Type, claim.Value); } Console.WriteLine(); if (!string.IsNullOrEmpty(result.IdentityToken)) { Console.WriteLine("Identity token:\n{0}", result.IdentityToken); } if (!string.IsNullOrEmpty(result.AccessToken)) { Console.WriteLine("Access token:\n{0}", result.AccessToken); } if (!string.IsNullOrWhiteSpace(result.RefreshToken)) { Console.WriteLine("Refresh token:\n{0}", result.RefreshToken); } } }
static async Task Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; var options = new OidcClientOptions { Authority = "https://localhost:5301", ClientId = "test", RedirectUri = "http://localhost:4000/oauth", Scope = "openid profile user_role classregisterapi.readwrite identityproviderapi.readwrite homeassignmentsapi.readwrite testingapi.readwrite", Flow = OidcClientOptions.AuthenticationFlow.AuthorizationCode, Browser = new NativeBrowser(), RefreshDiscoveryDocumentForLogin = true, LoadProfile = false }; options.Policy.Discovery.ValidateIssuerName = false; var oidcClient = new OidcClient(options); var loginResult = await oidcClient.LoginAsync(); if (loginResult.IsError) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Sikertelen bejelentkezés."); return; } Console.WriteLine("Sikeres bejelentkezés!"); Console.WriteLine("1 - Access token kiírása"); Console.WriteLine("2 - Bérlő kiválasztása"); while (true) { Console.Write("Választott lehetőség: "); var option = Console.ReadLine(); if (option == "1") { Console.WriteLine("Access token:"); Console.WriteLine(loginResult.AccessToken); Console.ReadLine(); return; } if (option == "2") { using var client = new HttpClient(); var response = await "https://localhost:5301/api/users/me" .WithOAuthBearerToken(loginResult.AccessToken) .GetJsonAsync <UserDetailsResponse>(); for (int i = 0; i < response.Tenants.Count; i++) { Console.WriteLine($"{i} - {response.Tenants[i].Name}"); } Console.Write("Választott bérlő: "); var tenantIndex = int.Parse(Console.ReadLine()); var tenantId = response.Tenants[tenantIndex].Id; var authorizeState = await oidcClient.PrepareLoginAsync(); var browser = new NativeBrowser(); var browserResult = await browser.InvokeAsync(new BrowserOptions(authorizeState.StartUrl, authorizeState.RedirectUri)); var code = HttpUtility.ParseQueryString(browserResult.Response).Get("code"); var result = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest { Address = "https://localhost:5301/connect/token", Code = code, GrantType = "authorization_code", ClientId = "test", RedirectUri = "http://localhost:4000/oauth", CodeVerifier = authorizeState.CodeVerifier, Parameters = new Dictionary <string, string> { { "tenant_id", tenantId.ToString() } } }); if (result.IsError) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Hiba történt a bejelentkezéskor."); return; } Console.WriteLine("Sikeres belejentkezés!"); Console.WriteLine("Access token:"); Console.WriteLine(result.AccessToken); Console.ReadLine(); return; } Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Ismeretlen lehetőség."); Console.ResetColor(); } }
public async Task Valid_response_with_profile_should_succeed() { _options.LoadProfile = true; var client = new OidcClient(_options); var state = await client.PrepareLoginAsync(); var url = $"?state={state.State}&nonce={state.Nonce}&code=bar"; var key = Crypto.CreateKey(); var idToken = Crypto.CreateJwt(key, "https://authority", "client", new Claim("at_hash", Crypto.HashData("token")), new Claim("sub", "123"), new Claim("nonce", state.Nonce)); var tokenResponse = new Dictionary <string, object> { { "access_token", "token" }, { "expires_in", 300 }, { "id_token", idToken }, { "refresh_token", "refresh_token" } }; var userinfoResponse = new Dictionary <string, object> { { "sub", "123" }, { "name", "Dominick" } }; _options.ProviderInformation.KeySet = Crypto.CreateKeySet(key); var networkHandler = new NetworkHandler(request => { if (request.RequestUri.AbsoluteUri.EndsWith("token")) { return(JsonConvert.SerializeObject(tokenResponse)); } else if (request.RequestUri.AbsoluteUri.EndsWith("userinfo")) { return(JsonConvert.SerializeObject(userinfoResponse)); } else { throw new InvalidOperationException("unknown netowrk request."); } }, HttpStatusCode.OK); _options.BackchannelHandler = networkHandler; var result = await client.ProcessResponseAsync(url, state); result.IsError.Should().BeFalse(); result.AccessToken.Should().Be("token"); result.IdentityToken.Should().NotBeNull(); result.User.Should().NotBeNull(); result.User.Claims.Count().Should().Be(2); result.User.Claims.First().Type.Should().Be("sub"); result.User.Claims.First().Value.Should().Be("123"); result.User.Claims.Skip(1).First().Type.Should().Be("name"); result.User.Claims.Skip(1).First().Value.Should().Be("Dominick"); }
private async void SignIn() { // create a redirect URI using an available port on the loopback address. string redirectUri = string.Format("http://127.0.0.1:7890/"); Console.WriteLine("redirect URI: " + redirectUri); // create an HttpListener to listen for requests on that redirect URI. var http = new HttpListener(); http.Prefixes.Add(redirectUri); Console.WriteLine("Listening.."); http.Start(); var options = new OidcClientOptions { Authority = "https://demo.identityserver.io", ClientId = "native.hybrid", Scope = "openid profile api", RedirectUri = redirectUri }; // "native", // "secret", // "openid profile api", // redirectUri) //{ // UseFormPost = true, // Style = OidcClientOptions.AuthenticationStyle.Hybrid //}; var client = new OidcClient(options); var state = await client.PrepareLoginAsync(); Console.WriteLine($"Start URL: {state.StartUrl}"); // open system browser to start authentication Process.Start(state.StartUrl); // wait for the authorization response. var context = await http.GetContextAsync(); var formData = GetRequestPostData(context.Request); // Brings the Console to Focus. BringConsoleToFront(); // sends an HTTP response to the browser. var response = context.Response; string responseString = string.Format("<html><head><meta http-equiv='refresh' content='10;url=https://demo.identityserver.io'></head><body>Please return to the app.</body></html>"); var buffer = Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; var responseOutput = response.OutputStream; await responseOutput.WriteAsync(buffer, 0, buffer.Length); responseOutput.Close(); Console.WriteLine($"Form Data: {formData}"); var result = await client.ProcessResponseAsync(formData, state); if (result.IsError) { Console.WriteLine("\n\nError:\n{0}", result.Error); } else { Console.WriteLine("\n\nClaims:"); foreach (var claim in result.User.Claims) { Console.WriteLine("{0}: {1}", claim.Type, claim.Value); } Console.WriteLine(); Console.WriteLine("Access token:\n{0}", result.AccessToken); if (!string.IsNullOrWhiteSpace(result.RefreshToken)) { Console.WriteLine("Refresh token:\n{0}", result.RefreshToken); } } http.Stop(); }
private async static Task SignInAsync() { // create a redirect URI using an available port on the loopback address. string redirectUri = string.Format("http://127.0.0.1:7890/"); // create an HttpListener to listen for requests on that redirect URI. var settings = new WebListenerSettings(); settings.UrlPrefixes.Add(redirectUri); var http = new WebListener(settings); http.Start(); Console.WriteLine("Listening.."); var options = new OidcClientOptions { Authority = _authority, ClientId = "native.hybrid", RedirectUri = redirectUri, Scope = "openid profile offline_access read api", ClientSecret = "secret", FilterClaims = true, LoadProfile = true, Flow = OidcClientOptions.AuthenticationFlow.Hybrid }; var serilog = new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.FromLogContext() .WriteTo.LiterateConsole(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}{Exception}{NewLine}") .CreateLogger(); options.LoggerFactory.AddSerilog(serilog); var client = new OidcClient(options); var state = await client.PrepareLoginAsync(); OpenBrowser(state.StartUrl); var context = await http.AcceptAsync(); var formData = GetRequestPostData(context.Request); if (formData == null) { Console.WriteLine("Invalid response"); return; } await SendResponseAsync(context.Response); var result = await client.ProcessResponseAsync(formData, state); options.Policy.ForceIntrospectionForAccessToken = true; //-- Test POP generation var testPop = client.CreatePopToken(new IdentityModel.OidcClient.Pop.EncodingParameters(options, result.AccessToken) { Method = "GET" }.ToJwtPayload(), result.PopTokenKey).ToSignedB64String(); Console.WriteLine($"Generated PoP Token: {testPop}"); //--Test validation... var testValidate = await client.ValidatePopToken(testPop, false, "read", "secret"); Console.WriteLine($"PoP Token Valid: {!testValidate.IsError}"); //--Test refresh var refreshResult = await client.RefreshTokenAsync(result.RefreshToken); var refreshValidate = client.CreatePopToken(new IdentityModel.OidcClient.Pop.EncodingParameters(options, refreshResult.AccessToken) { Method = "GET" }.ToJwtPayload(), refreshResult.PopTokenKey).ToSignedB64String(); var refreshValid = await client.ValidatePopToken(refreshValidate, false, "read", "secret"); var oldValidate = client.CreatePopToken(new IdentityModel.OidcClient.Pop.EncodingParameters(options, result.AccessToken) { Method = "GET" }.ToJwtPayload(), result.PopTokenKey).ToSignedB64String(); var oldValid = await client.ValidatePopToken(oldValidate, false, "read", "secret"); Console.WriteLine($"Generated PoP Token after refresh: {testPop}"); Console.WriteLine($"PoP Token (using refreshed access token) Valid: {!refreshValid.IsError}"); Console.WriteLine($"PoP Token (using old access token) Valid: {!oldValid.IsError}"); //Depending on how implemented - this should not work for an old token after the refresh token has been used. //--Revoke the tokens. var revokeClient = new TokenRevocationClient($"{options.Authority}/connect/revocation", options.ClientId, options.ClientSecret); var revokeResult = await revokeClient.RevokeRefreshTokenAsync(refreshResult.RefreshToken); Console.WriteLine($"Token revocation succeeded: {!revokeResult.IsError}"); ShowResult(result); }