Writing Bearer Token to Javascript - oauth-2.0

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

How to make API request from Google authentication in ASP.NET?

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.

Azure AD After Logging In Issues, Claims Are Null In Web Browser (Chrome, Firefox)

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()
});

oidc-client - signinredirect - doesn't redirect to redirect_uri

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)));

Connecting with Javascript to Web API protected by IdentityServer3

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)

WSO2 Identity Server with OpenId Connect

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");
}

Resources