Identity Server Not returning the Correct Access Token - identityserver3

I am makeing a call to identity server from angular2(java script client app), but its not returning the correct access_token, instead its returning something like
b8fee3ff98859c83e69b68376b413a542217cb9f054fc9638e885fe18650f880

Like the comments suggest, your client is returning reference tokens. If you want your client to get self contained access tokens make sure your client is of the form:
var angular_client = new Client
{
ClientId = "angular_client",
AccessTokenType = AccessTokenType.Jwt, //You probably have this set to .Reference
AccessTokenLifeTime = 3600,
AllowAccessTokensViaBrowser = true,
...
}

Related

.Net Core 3.1 SignalR Client - How to add the JWT Token string to SignalR connection configuration?

I am using the SignalR .net core client in my project with JWT Tokens.
In the sample code below, the string variable "tokenString" has already been configured as an actual token and therefore i don't need to call upon an external method to create the token, that part has already been done before I reach this method. Using debug, and also testing the "tokenString" value on JWT website, I know the token is working, its just the fact I dont know how to use the ready made token in the SignalR connection method.
How do I configure the SignalR client connection to use this tokenString?
localConConnection = new HubConnectionBuilder()
.WithUrl("https://localhost:44372/LocalConnectorHub", options =>
{
options.AccessTokenProvider = () => Task.FromResult(tokenString); // Not working
// Need a solution like this: options.Token = tokenString
})
.WithAutomaticReconnect()
.Build();
The issue was the fact that the [Authorize] attribute I had configured in the SignalR Hub class needed to define the authentication scheme to use, [Authorize] attribute alone was not enough.
SignalR Hub Class:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class LocalConnectorHub : Hub
{
public async Task SendToMacros(string serverName, string data)
{
await Clients.All.SendAsync("MacrosInbound", serverName, data);
}
public async Task ConnectorStatus(string serverName, string data)
{
await Clients.All.SendAsync("UpdateConnectorStatus", serverName, data);
}
}
SignalR .NET Core Client Connection:
localConConnection = new HubConnectionBuilder()
.WithUrl("https://localhost:44372/LocalConnectorHub", options =>
{
options.AccessTokenProvider = () => Task.FromResult(tokenString);
})
.WithAutomaticReconnect()
.Build();
await localConConnection.StartAsync();
Further example code from the startup.cs class (inside configure services method), this is posted to help one of our fellow members in the comments below:
// Retrieve the secret key from the appsettings.json file used for encryption
// when generating the JWT token for REST API authentication.
var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);
// Added to original .net core template.
// The preceding code configures multiple authentication methods. The app uses cookie-based authentication to log in
// via the browser using the identity manager. The second methid uses JWT bearer authentication for the REST API.
// The preceding cookie configuration configures Identity with default option values.
// Services are made available to the app through dependency injection.
// Cookie configuration MUST be called after calling AddIdentity or AddDefaultIdentity.
// IMPORTANT NOTE:
// When we decorate controllers or classes with use the [Authorize] attribute, it actually binds to the first authentication
// system by default (in this case cookie authentication) The trick is to change the attribute to specify which authorization
// service we want to use. Anexample for a protected respurce for a REST API controller would be to decorate using:
// "[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]"
services.AddAuthentication()
.AddCookie(options =>
{
// Cookie settings
options.Cookie.Name = "MyCompanyName";
// HttpOnly is a flag that can be used when setting a cookie to block access to the cookie from client side scripts.
// Javascript for example cannot read a cookie that has HttpOnly set. This helps mitigate a large part of XSS attacks
// as many of these attempt to read cookies and send them back to the attacker, possibly leaking sensitive information
// or worst case scenario, allowing the attacker to impersonate the user with login cookies.
options.Cookie.HttpOnly = true;
// CookieAuthenticationOptions.ExpireTimespan is the option that allows you to set how long the issued cookie is valid for.
// The cookie is valid for (XX) minutes from the time of creation. Once those XX minutes are up the user will have to sign
// back in becuase if the SlidingExpiration is set to false.
// If SlidingExpiration is set to true then the cookie would be re-issued on any request half way through the ExpireTimeSpan.
// For example, if the user logged in and then made a second request half way through the permitted timespan then the cookie
// would be re-issued for another (XX) minutes. If the user logged in and then made a second request AFTER (XX) minutes later
// then the user would be prompted to log in.
// You can also change the units i.e. TimeSpan.FromHours(10); OR TimeSpan.FromDays(10);
// In a nutshell, setting the options.ExpireTimeSpan is equivalent to setting an idle time out period...
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
options.LoginPath = "/Identity/Account/Login";
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
// Sliding expiration resets the expiration time for a valid authentication cookie if a request is made and more than half of the
// timeout interval has elapsed.If the cookie expires, the user must re - authenticate.Setting the SlidingExpiration property to
// false can improve the security of an application by limiting the time for which an authentication cookie is valid, based on the
// configured timeout value.
options.SlidingExpiration = true;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
// The "iss" (issuer) claim identifies the principal that issued the JWT. The processing of this
// claim is generally application specific. The "iss" value is a case-sensitive string containing
// a StringOrURI value. Use of this claim is OPTIONAL.
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
// The "iss" (issuer) claim identifies the principal that issued the JWT.The processing of this
// claim is generally application specific. The "iss" value is a case-sensitive string containing
// a StringOrURI value.Use of this claim is OPTIONAL.
ValidateIssuer = false,
// Usually, this is your application base URL
ValidIssuer = "http://localhost:45092/",
// The "aud" (audience) claim identifies the recipients that the JWT is intended for. Each principal
// intended to process the JWT MUST identify itself with a value in the audience claim. If the principal
// processing the claim does not identify itself with a value in the "aud" claim when this claim is present,
// then the JWT MUST be rejected. In the general case, the "aud" value is an array of case-sensitive strings,
// each containing a StringOrURI value. In the special case when the JWT has one audience, the "aud" value
// MAY be a single case-sensitive string containing a StringOrURI value. The interpretation of audience
// values is generally application specific. Use of this claim is OPTIONAL.
ValidateAudience = false,
//Here, we are creating and using JWT within the same application.
//In this case, base URL is fine.
//If the JWT is created using a web service, then this would be the consumer URL.
ValidAudience = "http://localhost:45092/",
// The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted
// for processing. The processing of the "exp" claim requires that the current date/time MUST be before the
// expiration date/time listed in the "exp" claim.
RequireExpirationTime = true,
// Check if token is not expired and the signing key of the issuer is valid (ValidateLifetime = true)
ValidateLifetime = true,
};
// We have to hook the OnMessageReceived event in order to
// allow the JWT authentication handler to read the access
// token from the query string when a WebSocket or
// Server-Sent Events request comes in.
// Sending the access token in the query string is required due to
// a limitation in Browser APIs. We restrict it to only calls to the
// SignalR hub in this code.
// See https://learn.microsoft.com/aspnet/core/signalr/security#access-token-logging
// for more information about security considerations when using
// the query string to transmit the access token.
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// If the request is for our hub...
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/hubs")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
Appsettings.json file (dont store keys here for production :)
"AppSettings": {
"Token": "secret key for jwt"
}

IdentityServer3 Guidance Needed

I have a scenario where a client has an OpenIdConnect (OIDC) token in their possession. The OIDC was issued from an external OIDC provider, I am not the OIDC provider, just the downstream consumer of it.
The goal is for the client to exchange said OIDC Token, for temporary credentials, or an accesstoken, which will then give them api access to more specific resources.
In my case, the OIDC represents a user. The client, has a ClientId/Secret, which is used to establish service-2-service trust. In the end I would like to have something that looks a lot like the CustomGrant token Request.
static TokenResponse GetCustomGrantToken()
{
var client = new TokenClient(
token_endpoint,
"custom_grant_client",
"cd19ac6f-3bfa-4577-9579-da32fd15788a");
var customParams = new Dictionary<string, string>
{
{ "some_custom_parameter", "some_value" }
};
var result = client.RequestCustomGrantAsync("custom", "read", customParams).Result;
return result;
}
where my customParams would contain the OIDC to my user.
Problem: I can get a token back from the GetCustomGrantToken call, however a follow up Webapi call fails to pass Authorization. i.e. Identity.isAuthenticated is false.
The it all works fine if I get a clientcredential token.
static TokenResponse GetClientToken()
{
var client = new TokenClient(
token_endpoint,
"silicon",
"F621F470-9731-4A25-80EF-67A6F7C5F4B8");
return client.RequestClientCredentialsAsync("api1").Result;
}
Had the CustomGrantToken worked I would have put my users account info in the claims, thus giving me context in the subsequent WebApi calls.
Any direction would be appreciated.

ADAL - ClientAssertionCertificate

We can successfully acquire a token using the following code:
var certificate = Certificate.Load("Client.pfx", "notasecret");
var authenticationContext = new AuthenticationContext(authority);
var clientAssertionCertificate = new ClientAssertionCertificate(clientId, certificate);
return await authenticationContext.AcquireTokenAsync(resource, clientAssertionCertificate);
The token doesnt seem to contain any information that we can use to identity the client. In our use case we have lots of daemon service clients that communicate to a API. We need to have some unique identified available on the server.
I also tried creating our own JWT token and added some public claims, such as name. However after requesting client assertion type using the following code fragment
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "clientid", clientId },
{ "resource", resource },
{ "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" },
{ "grant_type", "client_credentials" },
{ "client_assertion", jwt }
});
var httpClient = new HttpClient
{
BaseAddress = new Uri("https://login.windows.net/{guid}/")
};
var response = await httpClient.PostAsync("oauth2/token", content);
The return token had none of my custom information.
Question: Is there a way to pass custom claims using ClientAssertionCertificate flow? where the token returned has additional information.
There is currently no way of adding custom claims in tokens issued for applications.
The token you receive should contain the claims appid (which identifies the client_id of the application who requested the token) and tid (which indicates which azure AD tenant the app is operating on). Those two should be enough for you to identify the calling application. Now, if rather than the application you want to identify the process (as in, instance of application X running on server A and instance of application X running on server B) then I don't believe we have anything in Azure AD today that would help you to tell the two apart - for Azure AD if they have the same client_id and secret, they are the same application.

Reusing ClaimsPrincipal to authenticate against sharepoint online

I have an Office 365 account (using the latest SharePoint 2013 instance)
I also have a simple .net web app that is authenticating against Office 365, I created an AppPrincipalId and added it using New-MsolServicePrincipal powershell commmand.
This works correctly. I launch the app (in debug), it redirects to 365 login, I login, it comes back to the app, and I have derived a class from ClaimsAuthenticationManager and overriden the Authenticate method.
I can now see the ClaimsPrincipal, with the relevant claims and identity etc.
Now I would like to re-use this identity to programmatically access SharePoint.
My questions:
a) Will SharePoint permit this Identity (seeing that it was issued by sts.windows.net)
b) How can I reconstruct a valid JWT (or use the existing one), and encapsulate this in a HttpRequest using authentication bearer.
The code I am using is below - this is coming back 401 not authorized.
Any help would be highly appreciated.
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
{
List<Claim> claims = null;
claims = (from item in incomingPrincipal.Claims
where item.Type.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)
select item).ToList();
RNGCryptoServiceProvider cryptoProvider = new RNGCryptoServiceProvider();
byte[] keyForHmacSha256 = Convert.FromBase64String("Gs8Qc/mAF5seXcGHCUY/kUNELTE=");
// Create our JWT from the session security token
JWTSecurityToken jwt = new JWTSecurityToken
(
"https://sts.windows.net/myAppIdGuid/",
"00000003-0000-0ff1-ce00-000000000000", // sharepoint id
claims,
new SigningCredentials(
new InMemorySymmetricSecurityKey(keyForHmacSha256),
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
"http://www.w3.org/2001/04/xmlenc#sha256"),
DateTime.UtcNow,
DateTime.UtcNow.AddHours(1)
);
var validationParameters = new TokenValidationParameters()
{
AllowedAudience = "00000003-0000-0ff1-ce00-000000000000", // sharepoint id
ValidIssuer = "https://sts.windows.net/myAppIdGuid/", // d3cbe is my app
ValidateExpiration = true,
ValidateNotBefore = true,
ValidateIssuer = true,
ValidateSignature = true,
SigningToken = new BinarySecretSecurityToken(Convert.FromBase64String("mySecretKeyFromPowerShellCommand")),
};
JWTSecurityTokenHandler jwtHandler = new JWTSecurityTokenHandler();
var jwtOnWire = jwtHandler.WriteToken(jwt);
var claimPrincipal = jwtHandler.ValidateToken(jwtOnWire, validationParameters);
JWTSecurityToken parsedJwt = jwtHandler.ReadToken(jwtOnWire) as JWTSecurityToken;
HttpWebRequest endpointRequest =
(HttpWebRequest)HttpWebRequest.Create(
"https://MySharepointOnlineUrl/_api/web/lists");
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/json;odata=verbose";
endpointRequest.Headers.Add("Authorization",
"Bearer " + parsedJwt.RawData);
HttpWebResponse endpointResponse =
(HttpWebResponse)endpointRequest.GetResponse();
}
}
If your scenario is about consuming SharePoint Online data from a remote web app, you probably want to use the OAuth flow. You can't generate the token yourself. Instead you ask for consent to the user to access certain scopes (resource + permission). These two links should help
http://msdn.microsoft.com/en-us/library/office/apps/jj687470(v=office.15).aspx
http://jomit.blogspot.com.ar/2013/03/authentication-and-authorization-with.html

How do I convert an NSHttpCookie to a System.Net.Cookie in MonoTouch?

I have a MonoTouch iPhone app that does federated sign in via the Azure Access Control Service. The login is done via an embedded UIWebView browser. When the login is done, I want to transfer the cookie into my app. I have access to the
NSHttpCookieStorage.SharedStorage.Cookies
collection, so I can find the cookie. But in order to call the back end services, I need to have a
System.Net.Cookie
that I can put into a CookieContainer to send to the service.
How do I convert between the two... is this the only way?
NSHttpCookie cookie = NSHttpCookieStorage.SharedStorage.Cookies[0];
System.Net.Cookie newCookie = new System.Net.Cookie()
{
Name = cookie.Name,
Value = cookie.Value,
Version = (int) cookie.Version,
Expires = cookie.ExpiresDate,
Domain = cookie.Domain,
Path = cookie.Path,
Port = cookie.PortList[0].ToString(), // is this correct??
Secure = cookie.IsSecure,
HttpOnly = cookie.IsHttpOnly
};
Yes, that is how you could convert. Perhaps you should just make an extension method on NSHttpCookie? Then you could call something like:
var c = cookie.ToCLRCookie ();