I'm trying to do a Proof of Concept. I'm using Azure Active Directory and trying to implement OAuth in a legacy project.
Half of this project is using Web Forms, the other half is calling WebAPI in another project directly through javascript.
As a test, I obtain the Bearer Token though the AuthorizationCodeReceived notification event of the UseOpenIdConnectAuthentication. I quickly write the token to a page that is calling the WebAPI with the following code:
$.ajax({
url: baseVotingHeaderURL,
type: 'GET',
dataType: "json",
beforeSend: function(xhr){
xhr.setRequestHeader('Authorization', 'Bearer ' + XXXXXXXXXXXXXXXXX);
},
success: function(result) {
options.success(result);
},
error: function(err) {
options.error(err);
}
});
I can see in Fiddler that the token is being passed:
No Proxy-Authorization Header is present.
Authorization Header is present: Bearer XXXXXXXXXXXXXXXX (I've obviously substituted the token with X's)
I'm still getting an Unauthorized 401.
Why doesn't this work?
Below is the code from Startup.Auth.cs
app.SetDefaultSignInAsAuthenticationType( CookieAuthenticationDefaults.AuthenticationType );
app.UseCookieAuthentication( new CookieAuthenticationOptions( ) );
app.UseWindowsAzureActiveDirectoryBearerAuthentication( new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = "XXXXXX.onmicrosoft.com",
AuthenticationType = "OAuth2Bearer",
TokenValidationParameters = new TokenValidationParameters( )
{
ValidAudience = "https://XXXX.onmicrosoft.com/XXXXX"
}
} );
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
Authority = "https://login.microsoftonline.com/XXXXX.onmicrosoft.com",
PostLogoutRedirectUri = "https://XXXXXXX/gbl/Home.aspx",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse( );
context.Response.Redirect( "/Error?message=" + context.Exception.Message );
return Task.FromResult( 0 );
},
AuthorizationCodeReceived = context =>
{
var client = ClientId;
var key = "XXXXXXXXXXXXXXXXXXX=";
var credential = new ClientCredential( client, key );
var authority = String.Format( CultureInfo.InvariantCulture, #"https://login.microsoftonline.com/{0}", "XXXXX.onmicrosoft.com" );
var authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext( authority );
Uri redirectUri = new Uri( HttpContext.Current.Request.Url.GetLeftPart( UriPartial.Path ) );
var apiResourceId = "https://graph.windows.net";
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
context.Code, redirectUri, credential, apiResourceId );
EndpointAndTokenHelper.DecodeAndWrite( result.AccessToken );
System.Diagnostics.Debug.WriteLine( result.AccessToken );
return Task.FromResult( 0 );
}
}
} );
}
I was following the examples verbatim. However, the final parameter in the authContext.AquireTokenByAuthorizationCode should have been my WebAPI resource and not https://graph.windows.net.
I don't know why the examples use https://graph.windows.net.
Related
I do not understand how I can get the authorization code/access token to make a request.
This is my .AddGoogle():
builder.Services.AddAuthentication(o =>
{
o.DefaultChallengeScheme = "Google";
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie().AddGoogle("Google",options =>
{
IConfigurationSection auth = builder.Configuration.GetSection("Authentication:Google");
options.ClientId = auth["ClientId"];
options.ClientSecret = auth["ClientSecret"];
options.CallbackPath = "/Home";
options.AuthorizationEndpoint += "?prompt=consent";
options.SaveTokens = true;
options.Scope.Add(FitnessService.Scope.FitnessActivityRead);
});
So I log in / register, and then what?
I've tried this method
UserCredential credential;
var flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer()
{
ClientSecrets = new ClientSecrets()
{
ClientId = configuration.GetSection("Authentication:Google")["ClientId"],
ClientSecret = configuration.GetSection("Authentication:Google")["ClientSecret"]
},
Scopes = new[] {
FitnessService.Scope.FitnessActivityRead,
FitnessService.Scope.FitnessActivityWrite,
FitnessService.Scope.FitnessSleepRead,
FitnessService.Scope.FitnessSleepWrite
},
});
var token = new TokenResponse
{
AccessToken = "",
RefreshToken = ""
};
credential = new UserCredential(flow, "user", token);
FitnessService fitnessService = new FitnessService(new BaseClientService.Initializer()
{
ApplicationName = "Exrecise App",
HttpClientInitializer = credential
});
var resp = await fitnessService.Users.Sessions.List("me").ExecuteAsync();
But how do I get the tokens to begin with?
I even tried HttpClient (by pasting the token from OAuthplayground)
HttpClient http = new HttpClient();
var resp = await http.SendAsync(new HttpRequestMessage()
{
RequestUri = new UriBuilder("https://www.googleapis.com/fitness/v1/users/me/sessions").Uri,
Headers =
{
{ "Authorization","Bearer " }
},
Method = HttpMethod.Get
});
return Ok(await resp.Content.ReadAsStringAsync());
Same problem, how do I get the access token from the currently signed in user?
I looked everywhere, but every solution is either outdated or is unclear or just doesn't work for some reason.
After Logging in from Azure AD I am getting Claims Based Identity e.g. UserName, Logi-Email null and Authentication is also False in Browser Chrome, Firefox but not in Microsoft Edge. This usually happens randomly and also when I log-out and re-login in Chrome browser the user authentication shows false in debug mode and claims are null. Let me know whats the problem area, I have researched with no avail.
Note- AddAuthentication().AddOpenIdConnect are for asp.netcore where as I am using asp.net mvc 5
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// AuthenticationMode = AuthenticationMode.Passive,
ClientId = ClientId,
Authority = AuthenticationConfig.Authority,
RedirectUri = AuthenticationConfig.RedirectUri,
PostLogoutRedirectUri = AuthenticationConfig.PostLogoutRedirectUri,
Scope = AuthenticationConfig.BasicSignInScopes,
ResponseType = OpenIdConnectResponseType.IdToken,
TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = false, NameClaimType = "name" }, //this.BuildTokenValidationParameters(),
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = (context) =>
{
// This ensures that the address used for sign in and sign out is picked up dynamically from the request
// this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
// Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
string appRedirectUri = string.Format("{0}://{1}{2}", context.Request.Scheme, (context.Request.Host.ToString() + context.Request.PathBase), AuthenticationConfig.RedirectUriAbsolutePath);
string postLogOutRedirectUri = string.Format("{0}://{1}{2}", context.Request.Scheme, (context.Request.Host.ToString() + context.Request.PathBase), "/Dashboard/Index");
context.ProtocolMessage.RedirectUri = appRedirectUri;
context.ProtocolMessage.PostLogoutRedirectUri = postLogOutRedirectUri;
return Task.FromResult(0);
},
SecurityTokenValidated = (context) =>
{
// retrieve caller data from the incoming principal
//string issuer = context.AuthenticationTicket.Identity.FindFirst("iss").Value;
//string Upn = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;
//string tenantId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
//if (
// //the caller comes from an admin-consented, recorded issuer
// (this.db.Tenants.FirstOrDefault(a => ((a.IssValue == issuer) && (a.AdminConsented))) == null)
// // the caller is recorded in the db of users who went through the individual on-boarding
// && (this.db.Users.FirstOrDefault(b => ((b.UPN == Upn) && (b.TenantID == tenantId))) == null)
// )
// // the caller was neither from a trusted issuer or a registered user -throw to block the authentication flow
// throw new UnauthorizedAccessException("Please use the Sign-up link to sign -up for the ToDo list application.");
return Task.FromResult(0);
},
AuthorizationCodeReceived = (context) =>
{
//var code = context.Code;
//ClientCredential credential = new ClientCredential(ClientId, AppKey);
//string tenantId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
//string signedInUserId = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
//AuthenticationContext authContext = new AuthenticationContext(AadInstance + tenantId, new ADALTokenCache(signedInUserId));
//// The following operation fetches a token for Microsoft graph and caches it in the token cache
//AuthenticationResult result = authContext.AcquireTokenByAuthorizationCodeAsync(
// code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, GraphResourceId).Result;
return Task.FromResult(0);
},
AuthenticationFailed = (context) =>
{
context.Response.Redirect("/Error/ShowError?signIn=true&errorMessage=" + context.Exception.Message);
context.HandleResponse(); // Suppress the exception
return Task.FromResult(0);
}
},
SignInAsAuthenticationType = "Cookies"
});
}
So after 1 week of Research. Below code in Startup.Auth.cs solved my problem.
Reference: ASP.NET_SessionId + OWIN Cookies do not send to browser
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieManager = new SystemWebCookieManager()
});
I'm using OIDC client and I'm calling below line to signin:
public signinRedirect(args?: any): Promise<any> {
return this.oidcUserManager.signinRedirect(args);
}
After this it goes to ID server login page and after login I see it is calling below in network tab:
https://localhost:50000/connect/authorize/callback?client_id=xxxxx
And after this it calls URL:
https://localhost:50000/Account/Login?ReturnUrl=%2Fconnect%2
It stays in ID server and doesn't redirect back to my SPA application with redirect_url.
Client configuration:
private createUserManager(): UserManager {
const authSettings: any = {
authority: "https://localhost:50000/",
clientId: "xxx.web.local",
loginRedirect: "http://localhost:1436/callback",
logoutRedirect: "http://localhost:1436/",
scope: "openid profile roles email offline_access api",
idleRefreshTime: 330
}; // APP_CONFIG.authSettings;
const oidcSettings = {
authority: authSettings.authority,
client_id: authSettings.clientId,
redirect_uri: authSettings.loginRedirect,
silent_redirect_uri: authSettings.loginRedirect + '-silent.html',
post_logout_redirect_uri: authSettings.logoutRedirect,
response_type: "id_token token",
scope: authSettings.scope,
automaticSilentRenew: false,
accessTokenExpiringNotificationTime: authSettings.idleRefreshTime,
filterProtocolClaims: true,
loadUserInfo: true,
};
return new this.window.Oidc.UserManager(oidcSettings);
ID server - Startup file
var identityServer = services.AddIdentityServer(options =>
{
if (authServerSettings.CookieLifetime.HasValue) options.Authentication.CookieLifetime = new TimeSpan(0, 0, authServerSettings.CookieLifetime.Value, 0);
if (authServerSettings.CookieSlidingExpiration.HasValue) options.Authentication.CookieSlidingExpiration = authServerSettings.CookieSlidingExpiration.Value;
//options.Authentication.de
options.Authentication.CookieAuthenticationScheme = IdentityServerConstants.DefaultCookieAuthenticationScheme;
options.Authentication.RequireCspFrameSrcForSignout = false;
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
// options.UserInteraction.CustomRedirectReturnUrlParameter = "https://localhost:1430/callback1";
})
var authentication = services.AddAuthentication(IdentityServerConstants.DefaultCookieAuthenticationScheme);
logic to redirect to SPA in ID server after authentication
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, user.UserName));
claims.Add(new Claim(JwtClaimTypes.Subject, user.Id));
// issue authentication cookie with subject ID and username
await HttpContext.SignInAsync(new ClaimsPrincipal(new ClaimsIdentity(claims)));
I have a Asp.NET MVC / WebAPI project with an embedded IdentityServer3.
I want both MVC and WebAPI to be protected by the IdentityServer. So I have used Authorize attribute on both MVC controllers and API controllers.
When surfing to my test page (which is protected) I get redirected to the IdentityServer login page. I enter my username and password and get authenticated and redirected back.
On the page I have a button that triggers a GET from javascript, with my access token in the authorization header, to my protected API. But here it fails with a 401 Unauthorized.
I get the access token to javascript by rendering it to the page with Razor.
I have 1 client in the IdentityServer set to hybrid flow. MVC uses cookies, while the API uses bearer tokens.
On my API HttpConfiguration I have set SuppressDefaultHostAuthentication. If I remove that line everything works, but then it uses cookies for the API which I don't want.
I use only HTTP and RequireSsl=false for now to avoid potential certificate problems.
I have tried for days to get this to work but I'm getting nowhere.
I don't even know how to debug this to get to cause of the 401.
By now I recognize just about every page that google suggests when I search for help.
Any ideas what it could be or how to debug this?
Here is my Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Trace()
.CreateLogger();
// MVC client
string authBaseAddress = "http://localhost:50319/identity";
string tokenEndpoint = authBaseAddress + "/connect/token";
string userInfoEndpoint = authBaseAddress + "/connect/userinfo";
string redirectUri = "http://localhost:50319/";
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "hybrid_clients",
Authority = authBaseAddress,
RedirectUri = redirectUri,
ResponseType = "code id_token token",
Scope = "openid profile roles sampleApi offline_access",
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
},
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
// use the code to get the access and refresh token
var tokenClient = new TokenClient(
tokenEndpoint,
"hybrid_clients",
"secret");
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
// use the access token to retrieve claims from userinfo
var userInfoClient = new UserInfoClient(
new Uri(userInfoEndpoint),
tokenResponse.AccessToken);
var userInfoResponse = await userInfoClient.GetAsync();
// create new identity
var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);
id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
n.AuthenticationTicket = new AuthenticationTicket(
new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
n.AuthenticationTicket.Properties);
},
// Attach the id_token for the logout roundtrip to IdentityServer
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
}
return Task.FromResult(0);
}
}
});
AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
// web api
app.Map("/api", a =>
{
var config = new HttpConfiguration();
a.UseCors(CorsOptions.AllowAll);
a.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
//AuthenticationMode = AuthenticationMode.Active,
Authority = authBaseAddress,
RequiredScopes = new[] { "sampleApi" },
DelayLoadMetadata = true
});
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.MapHttpAttributeRoutes();
a.UseWebApi(config);
});
// Identity server
app.Map("/identity", idsrvApp =>
{
idsrvApp.UseCors(CorsOptions.AllowAll);
idsrvApp.UseIdentityServer(new IdentityServerOptions
{
SiteName = "Embedded IdentityServer",
SigningCertificate = LoadCertificate(),
Factory = new IdentityServerServiceFactory()
.UseInMemoryUsers(Users.Get())
.UseInMemoryClients(Clients.Get())
.UseInMemoryScopes(Scopes.Get()),
AuthenticationOptions = new IdentityServer3.Core.Configuration.AuthenticationOptions()
{
EnablePostSignOutAutoRedirect = true // Automatically redirects back to the client on signout
},
RequireSsl = false,
});
});
}
X509Certificate2 LoadCertificate()
{
return new X509Certificate2(
string.Format(#"{0}\bin\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test");
}
}
My client
new Client
{
Enabled = true,
ClientName = "Hybrid Clients",
ClientId = "hybrid_clients",
Flow = Flows.Hybrid,
//AllowAccessTokensViaBrowser = false,
RedirectUris = new List<string>
{
"http://localhost:50319/"
},
PostLogoutRedirectUris = new List<string>
{
"http://localhost:50319/"
},
AllowedScopes = new List<string>
{
"openid",
"profile",
"email",
"roles",
"address",
"all_claims",
"sampleApi",
"offline_access"
},
ClientSecrets = new List<Secret>
{
new Secret("secret".Sha256())
},
AccessTokenType = AccessTokenType.Reference,
LogoutSessionRequired = true
},
My scopes
public static class Scopes
{
public static IEnumerable<Scope> Get()
{
var scopes = new List<Scope>
{
StandardScopes.OpenId,
StandardScopes.Profile,
StandardScopes.Email,
StandardScopes.Address,
StandardScopes.OfflineAccess,
StandardScopes.RolesAlwaysInclude,
StandardScopes.AllClaims,
new Scope
{
Enabled = true,
Name = "roles",
Type = ScopeType.Identity,
Claims = new List<ScopeClaim>
{
new ScopeClaim("role")
}
},
new Scope
{
Enabled = true,
DisplayName = "Sample API",
Name = "sampleApi",
Description = "Access to a sample API",
Type = ScopeType.Resource
}
};
return scopes;
}
}
My API
[Authorize]
public class SecuredApiController : ApiController
{
public IHttpActionResult Get()
{
var user = User as ClaimsPrincipal;
var claims = from c in user.Claims
select new
{
type = c.Type,
value = c.Value
};
return Json(claims);
}
}
Part of my Razor view
<button data-bind="click:callApi">Call API</button>
<span data-bind="text:apiResult"></span>
<script>
$(function() {
ko.myViewModel = new ClientAppViewModel('#ViewData["access_token"]');
ko.applyBindings(ko.myViewModel);
});
</script>
My JavaScript (KnockoutJS) that calls SecuredApi
function ClientAppViewModel(accessToken) {
var self = this;
self.accessToken = accessToken;
self.apiResult = ko.observable('empty');
self.callApi = function () {
console.log('CallApi');
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:50319/api/SecuredApi");
xhr.onload = function () {
self.apiResult(JSON.stringify(JSON.parse(xhr.response), null, 2));
};
xhr.setRequestHeader("Authorization", "Bearer " + self.accessToken);
xhr.send();
}
}
The Katana logs for the API are what you want. With these you will see why the API is returning a 401.
You can access these using the Microsoft.Owin log source (see Katana Documentation)
I am trying to use WSO2 Identity Server (5.1.0) with Asp.Net MVC, as a proof of concept i created a sample asp.net MVC project in visual studio 2015.
Following the WSO2 Guide, i have configured the identity server as required.
https://docs.wso2.com/display/IS510/OpenID+Connect+with+the+WSO2+Identity+Server+and+WSO2+OAuth2+Playground
On the sample application, i have added reference to Microsoft.Owin.Security.OpenIdConnect and added code to ConfigureAuth in Startup.Auth.cs file.
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = ""
//});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "SENmQQ9fOWcrqXjK1u3lXINhXtEa",
ClientSecret = "bFBJQqj4GT2Wfv8735fTTuHh3Isa",
Authority = "https://localhost:9443",
RedirectUri = "https://wso2openid.local.co.uk/Account/ExternalLoginCallback",
SignInAsAuthenticationType = "ClientCredCookie",
ResponseType = "id_token token",
Scope = "openid",
Configuration = new OpenIdConnectConfiguration
{
AuthorizationEndpoint = "https://localhost:9443/oauth2/authorize",
TokenEndpoint = "https://localhost:9443/oauth2/token"
},
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = n =>
{
return Task.FromResult(0);
},
SecurityTokenReceived = n =>
{
return Task.FromResult(0);
},
AuthorizationCodeReceived = n =>
{
return Task.FromResult(0);
},
SecurityTokenValidated = n =>
{
var token = n.ProtocolMessage.AccessToken;
// persist access token in cookie
if (!string.IsNullOrEmpty(token))
{
n.AuthenticationTicket.Identity.AddClaim(
new Claim("access_token", token));
}
return Task.FromResult(0);
},
AuthenticationFailed = notification =>
{
if (string.Equals(notification.ProtocolMessage.Error, "access_denied", StringComparison.Ordinal))
{
notification.HandleResponse();
notification.Response.Redirect("/");
}
return Task.FromResult<object>(null);
}
}
});
}
When i run the application, on login it redirects to WSO2 Identity Server login and manage to login but when it redirect to Account\ExternalLoginCallback, the logininfo is always null.
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
Any advise as to why this is not working will be appreciated.?
NB: I tried to put a break point on SecurityTokenValidated but it did not hit that break point. The only breakpoint which i got hit was RedirectToIdentityProvider.
It's work well for me:
Step1 : Config WSO2 with this:
https://docs.wso2.com/display/IS570/Logging+in+to+a+.NET+application+using+the+Identity+Server
Step2:
public async Task<RedirectResult> LoginOAuth()
{
var url = "https://localhost:9443/oauth2/authorize?response_type=code&client_id=5a8urZQAc0r4R7iUS9ar1wOoq9Ma&scope=openid&redirect_uri=http://localhost:49545/Home/GetCode";
var client = new HttpClient();
var response = await client.GetAsync(url);
string urlDistance = response.RequestMessage.RequestUri.ToString();
client.Dispose();
return Redirect(urlDistance);
}
public async Task<RedirectToRouteResult> GetCode()
{
//باشد GetCode همشون حتما باید
var client = new HttpClient();
string code = Request.QueryString["code"];
string sessionState = Request.QueryString["session_state"];
string client_id = Request.QueryString["client_id"];
client.Dispose();
//از طریق ارسال کد میخواد توکن رو بگیره
//****************
var values = new Dictionary<string, string>
{
{ "code", code },
{ "sessionState", sessionState },
{ "client_id", "5a8urZQAc0r4R7iUS9ar1wOoq9Ma" },
{ "client_secret", "b0yefcCc4ftVYJm7ffQi2IZZ0eMa" },
{ "grant_type", "authorization_code" },
{ "redirect_uri", "http://localhost:49545/Home/GetCode" }//??????????????
};
var content = new FormUrlEncodedContent(values);
client = new HttpClient();
var response2 = await client.PostAsync("https://localhost:9443/oauth2/token", content);
string responseString = await response2.Content.ReadAsStringAsync();
JObject jsonResult = JObject.Parse(responseString);
string access_token = jsonResult["access_token"].ToString();
string refresh_token = jsonResult["refresh_token"].ToString();
string scope = jsonResult["scope"].ToString();
string id_token = jsonResult["id_token"].ToString();
string token_type = jsonResult["token_type"].ToString();
string expires_in = jsonResult["expires_in"].ToString();
//**************
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://localhost:9443/oauth2/userinfo?schema=openid");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", access_token);
string result = await httpClient.GetStringAsync("/oauth2/userinfo?schema=openid");
return RedirectToAction("Contact");
}