I'm following the Identity Server 4 Quickstart and I'm having a weird issue even though I followed it step by step.
It says (translated from German) connection denied by target computer.
Whats weird about this is that in the API project "we"(I) said ValidateAudience = false which I thought meant that tokens aren't being validated at all.
// call api
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);
var response = await apiClient.GetAsync("https://localhost:6001/identity");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
I am truly confused.The Client does get an accessToken so that's not the problem ... I hope.
Github-Repo
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
[16:15:42 Debug] IdentityServer4.Endpoints.TokenEndpoint
Start token request.
[16:15:42 Debug] IdentityServer4.Validation.ClientSecretValidator
Start client validation
[16:15:42 Debug] IdentityServer4.Validation.BasicAuthenticationSecretParser
Start parsing Basic Authentication secret
[16:15:42 Debug] IdentityServer4.Validation.PostBodySecretParser
Start parsing for secret in post body
[16:15:42 Debug] IdentityServer4.Validation.ISecretsListParser
Parser found secret: PostBodySecretParser
[16:15:42 Debug] IdentityServer4.Validation.ISecretsListParser
Secret id found: client
[16:15:42 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client client succeeded.
[16:15:42 Debug] IdentityServer4.Validation.ISecretsListValidator
Secret validator success: HashedSharedSecretValidator
[16:15:42 Debug] IdentityServer4.Validation.ClientSecretValidator
Client validation success
[16:15:42 Debug] IdentityServer4.Validation.TokenRequestValidator
Start token request validation
[16:15:42 Debug] IdentityServer4.Validation.TokenRequestValidator
Start client credentials token request validation
[16:15:42 Debug] IdentityServer4.Validation.TokenRequestValidator
client credentials token request validation success
[16:15:42 Information] IdentityServer4.Validation.TokenRequestValidator
Token request validation success, {"ClientId": "client", "ClientName": null, "GrantType": "client_credentials", "Scopes": "api1", "AuthorizationCode": null, "RefreshToken": null, "UserName": null, "AuthenticationContextReferenceClasses": null, "Tenant": null, "IdP": null, "Raw": {"grant_type": "client_credentials", "scope": "api1", "client_id": "client", "client_secret": "***REDACTED***"}, "$type": "TokenRequestValidationLog"}
[16:15:42 Debug] IdentityServer4.Services.DefaultClaimsService
Getting claims for access token for client: client
[16:15:42 Debug] IdentityServer4.Endpoints.TokenEndpoint
Token request success.
I think setting ValidateAudience = false will just ignore the audience claim, but still validate the other things in the token.
You can set the IncludeErrorDetails property to true and like this:
.AddJwtBearer(options =>
{
options.Audience = "payment";
options.Authority = "https://localhost:6001/";
//True if token validation errors should be returned to the caller.
options.IncludeErrorDetails = true;
When you set it to True, then you will get more details in the response header, like:
HTTP/1.1 401 Unauthorized
Date: Sun, 02 Aug 2020 11:19:06 GMT
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"
To further help you out, please post a sample access token and API configuration (Startup class)
See this article for further details
So in API/Properties/lauchsettings .... when generating the project it used a default sheme and in that sheme it sets a port of 43033 or smth
Related
I'm having some issues with an ASP.NET Core 6 Web API and a react front end using firebase auth. I get a 401 every time the react app requests an authorized endpoint (but 200 with postman).
Using ASP.NET Core 6
I know the token I am using works fine because when I request with postman using the same bearer token I get a 200 response.
I have also tried to set ValidateIssuer = false & ValidateAudience = false & ValidateLifetime = false with no luck
Front end request (when the user logs in via the firebase/auth signInWithEmailAndPassword method
const testFetch = async () => {
getIdToken(auth.currentUser!).then(async (token) => {
const res = await fetch('https://localhost:51437/test/private', {
method: 'GET',
headers: {
Authentication: `Bearer ${token}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
const result = await res.json();
console.log(result);
});
};
I can also request non authorized endpoints from my web app and get them correctly so shouldn't be anything to do with cors
Adding JWT bearer auth scheme:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
opt.IncludeErrorDetails = true;
opt.Authority = $"https://securetoken.google.com/{builder.Configuration["Firebase:ID"]}";
opt.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuer = true,
ValidIssuer = $"https://securetoken.google.com/{builder.Configuration["Firebase:ID"]}",
ValidateAudience = true,
ValidAudience = builder.Configuration["Firebase:ID"],
ValidateLifetime = true
};
});
Setup for auth:
app.UseCors(x => x.AllowAnyMethod().AllowAnyHeader().SetIsOriginAllowed(origin => true).AllowCredentials());
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();
app.Run();
Controller:
[ApiController]
[Route("[controller]")]
public class TestController : Controller
{
public IActionResult Index()
{
return Ok("Hello world");
}
[HttpGet("private")]
[Authorize]
public IActionResult Private()
{
return Ok(new
{
Message = "Hello from a private endpoint!"
});
}
}
Request logs
[00:41:14 DBG] AuthenticationScheme: Bearer was not authenticated.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Information: Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
[00:41:14 INF] Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Information: AuthenticationScheme: Bearer was challenged.
[00:41:14 INF] AuthenticationScheme: Bearer was challenged.
After debugging it looks like my API seems to be removing the Authorization header from my front end app which is an expo web app (react) but not when the request is from postman.
The request is sent at-least in the network tab with the correct bearer
I am trying to redirect request from protected_api() to login() function in fastapi. but it fails with messages
Failed to fetch.
Possible Reasons:
CORS
Network Failure
URL scheme must be "http" or "https" for CORS request.
what could be the issue and how can be redirect from one api to other
#app.get("/protected_api")
async def protected_api():
resp = RedirectResponse("https://localhost:5000/token")
return resp
#app.post("/token", response_model=Token)
async def login(form_data: OAuth2PasswordRequestForm = Depends()): # login function to get access token
print('In login fun value of form_data dict.....%s' % form_data.__dict__)
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(seconds=ACCESS_TOKEN_EXPIRE_SECONDS)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
print('Value of access_token in login fun ......%s\n' % access_token)
return {"access_token": access_token, "token_type": "bearer"}
You're having clients ping A (/protected_api) but sending a response from B (/token). They are not the same endpoint, so this involves CORS. Try using CORSMiddleware with FastAPI to resolve this issue.
I have IdentityServer and a separate WebApi project using resource owner flow.
When I request a token as below the token is issued and can be used to access the WebApi. So I assume IdentityServer is setup correctly, and the WebApi project is setup correctly as well.
username=user1
password=user1password
grant_type=password
client_id=myClientId
client_secret=myClientSecret
scope=api1
Now when I change the grant type to refresh and the scope to offline_access I get a refresh token. I then use the refresh token to get an access token, but when I use the access token to request the WebApi it is rejected.
With an error
the audience is invalid
I suspect it's because I am asking for an offline_access scope instead of api1 scope which the WebApi project expects. How do I get a refresh token that can use used with the scope api1?
var model = {
client_id: "myClientId",
client_secret: "myClientSecret",
scope: "api1 offline_access",
token_type: "Bearer", //Optional
grant_type: "refresh_token",
refresh_token: "your refresh token"
};
//this is most important step when to use refresh token
var base64 = btoa(model.client_id + ":" + model.client_secret);
//and your request here
this.$http({
method: "POST",
url: "/connect/token",
headers: {
'content-type': "application/x-www-form-urlencoded",
'Authorization': "Basic " + base64
},
data: jQuery.param(model)
})
.then(
response => {
//success
},
response => {
//logout
});
I am trying to authenticate an existing MVC application built with old Asp.Net (not the core version) with MVC framework.
By following IdentityServer4 and IdentityServer3 examples I have managed to get to a point where my user information is stored in LocalDB using EntityFramework and when I try to access to a restricted page in my client application I get redirected to the Login page provided by the IdentityServer4. However after successful login (based on what I see on the log) It does not redirect to the appropriate page. Address bar stays with something like http://localhost:5000/.... followed by lots of parameters and hashed values. Port 5000 is where I run my identity server and my application is hosted at port 44300 yet I couldn't manage to get back to there.
Has someone faced this kind of issue before or can someone please point me to an example which consists of IdentityServer4 along with a none Core version of Asp.Net.
Edit 1: Implementation Details
Server: IdentityServer4 implementation is almost clone of IdentityServer4 Quickstarts 6-AspNetIdentity.
Config File:
public class Config
{
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}
// clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
// client credentials client
return new List<Client>
{
new Client
{
ClientId = "webapp",
ClientName = "Client WebApp",
AllowedGrantTypes = GrantTypes.Hybrid,
RedirectUris = { "http://localhost:44300/signin-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
},
AllowOfflineAccess = true
}
};
}
}
Client: Client implementation I am using is a dummy and It originates from IdentityServer3 Client examples "MVC OWIN Client (Hybrid)".
Startup.cs:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
SignInAsAuthenticationType = "Cookies",
ClientSecret = "secret",
Authority = "http://localhost:5000", //ID Server
RedirectUri = "http://localhost:44300/signin-oidc",
ClientId = "webapp",
ResponseType = "id_token code",
Scope = "openid profile",
});
}
}
Log Output: Log output after clicking secured page -> IS Login Page -> Clicking Login.
...
...
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[3]
HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Identity.Application.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
AuthenticationScheme: Identity.Application was successfully authenticated.
dbug: IdentityServer4.Hosting.EndpointRouter[0]
Request path /connect/authorize/login matched to endpoint type Authorize
dbug: IdentityServer4.Hosting.EndpointRouter[0]
Mapping found for endpoint: Authorize, creating handler: IdentityServer4.Endpoints.AuthorizeEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeEndpoint for /connect/authorize/login
dbug: IdentityServer4.Endpoints.AuthorizeEndpoint[0]
Start authorize request (after login)
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
AuthenticationScheme: Identity.Application was successfully authenticated.
dbug: IdentityServer4.Endpoints.AuthorizeEndpoint[0]
User in authorize request: df21b123-d4b6-40ef-beed-e918bdfd56e9
dbug: IdentityServer4.Validation.AuthorizeRequestValidator[0]
Start authorize request protocol validation
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
AuthenticationScheme: Identity.Application was successfully authenticated.
dbug: IdentityServer4.Validation.AuthorizeRequestValidator[0]
Calling into custom validator: IdentityServer4.Validation.DefaultCustomAuthorizeRequestValidator
info: IdentityServer4.Endpoints.AuthorizeEndpoint[0]
ValidatedAuthorizeRequest
{
"ClientId": "webapp",
"ClientName": "Client WebApp",
"RedirectUri": "http://localhost:44300/signin-oidc",
"AllowedRedirectUris": [
"http://localhost:44300/signin-oidc"
],
"SubjectId": "df21b123-d4b6-40ef-beed-e918bdfd56e9",
"ResponseType": "code id_token",
"ResponseMode": "form_post",
"GrantType": "hybrid",
"RequestedScopes": "openid profile",
"State": "OpenIdConnect.AuthenticationProperties=m1ybV84KFOLgklhcmtb8iR6VFuDBxWSzJKpTy83w7RF3zRTwd9zHBbdSyiAHbuea2D6FM1MjCJvMbql9qjcTntyu95POoCAWGwDML0nkiaYnKPKtJxgZ7FagyvYvz87C6pYlJWmL2zbrTFkYh7IPmX-Qv9rPOfyp4uwhhbZZ731vfL1mSxuhh_p1dPVNFJJav4E8bZXyadg94EXJbqb3ecc_jQHWn1F_eiJsoVMSRdk",
"Nonce": "636268234716844341.OTFhNGE1ZTEtNTMyYy00Y2MyLWFjOGMtMDE1NjBmNDY3ZGM1NWFmNzIxMjItYTgzZC00NjJhLTk4YWMtNDExOTA0N2I4MjNl",
"SessionId": "61d148313b2a7485dd27e3110ea61fff",
"Raw": {
"client_id": "webapp",
"redirect_uri": "http://localhost:44300/signin-oidc",
"response_mode": "form_post",
"response_type": "id_token code",
"scope": "openid profile",
"state": "OpenIdConnect.AuthenticationProperties=m1ybV84KFOLgklhcmtb8iR6VFuDBxWSzJKpTy83w7RF3zRTwd9zHBbdSyiAHbuea2D6FM1MjCJvMbql9qjcTntyu95POoCAWGwDML0nkiaYnKPKtJxgZ7FagyvYvz87C6pYlJWmL2zbrTFkYh7IPmX-Qv9rPOfyp4uwhhbZZ731vfL1mSxuhh_p1dPVNFJJav4E8bZXyadg94EXJbqb3ecc_jQHWn1F_eiJsoVMSRdk",
"nonce": "636268234716844341.OTFhNGE1ZTEtNTMyYy00Y2MyLWFjOGMtMDE1NjBmNDY3ZGM1NWFmNzIxMjItYTgzZC00NjJhLTk4YWMtNDExOTA0N2I4MjNl",
"x-client-SKU": "ID_NET",
"x-client-ver": "1.0.40306.1554"
}
}
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[#__get_Item_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [e].[Id], [e].[AccessFailedCount], [e].[ConcurrencyStamp], [e].[DefaultDatabaseName], [e].[DefaultDatabaseServer], [e].[Email], [e].[EmailConfirmed], [e].[HierarchyIds], [e].[LockoutEnabled], [e].[LockoutEnd], [e].[NormalizedEmail], [e].[NormalizedUserName], [e].[PasswordHash], [e].[PhoneNumber], [e].[PhoneNumberConfirmed], [e].[SecurityStamp], [e].[TwoFactorEnabled], [e].[UserName]
FROM [AspNetUsers] AS [e]
WHERE [e].[Id] = #__get_Item_0
info: IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator[0]
Showing consent: User has not yet consented
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 138.8585ms 302
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/consent?returnUrl=%2Fconnect%2Fauthorize%2Fconsent%3Fclient_id%3Dwebapp%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A44300%252Fsignin-oidc%26response_mode%3Dform_post%26response_type%3Did_token%2520code%26scope%3Dopenid%2520profile%26state%3DOpenIdConnect.AuthenticationProperties%253Dm1ybV84KFOLgklhcmtb8iR6VFuDBxWSzJKpTy83w7RF3zRTwd9zHBbdSyiAHbuea2D6FM1MjCJvMbql9qjcTntyu95POoCAWGwDML0nkiaYnKPKtJxgZ7FagyvYvz87C6pYlJWmL2zbrTFkYh7IPmX-Qv9rPOfyp4uwhhbZZ731vfL1mSxuhh_p1dPVNFJJav4E8bZXyadg94EXJbqb3ecc_jQHWn1F_eiJsoVMSRdk%26nonce%3D636268234716844341.OTFhNGE1ZTEtNTMyYy00Y2MyLWFjOGMtMDE1NjBmNDY3ZGM1NWFmNzIxMjItYTgzZC00NjJhLTk4YWMtNDExOTA0N2I4MjNl%26x-client-SKU%3DID_NET%26x-client-ver%3D1.0.40306.1554
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[3]
HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Identity.Application.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 32.5652ms 404
Your application running an older version of .NET isn't relevant.
In this video, one of the authors of IdentityServer demonstrates how he was able to connect a WinForm application with IDS4.
The communication to the IDS4 is made through HTTP requests, your client could be anything really as long as it can handle the communication with the IDS4.
I suggest that you open fiddler and monitor the requests to view the parameters passing.
You could also use one of the quickstarts as a base to your IDS, or compare it to your setup to check what's wrong.
From your logs, it is showing that your user has not yet consented to the scopes being requested and so is attempting to navigate to a page on the Identity Server where the user can consent.
`Request starting HTTP/1.1 GET http://localhost:5000/consent?returnUrl=%2Fconnect%2Fauthorize%2Fconsent%3Fclient_id%3Dwebapp%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A44300%252Fsignin-oidc%26response_mode%3Dform_post%26response_type%3Did_token%2520code%26scope%3Dopenid%2520profile%26state%3DOpenIdConnect.AuthenticationProperties%253Dm1ybV84KFOLgklhcmtb8iR6VFuDBxWSzJKpTy83w7RF3zRTwd9zHBbdSyiAHbuea2D6FM1MjCJvMbql9qjcTntyu95POoCAWGwDML0nkiaYnKPKtJxgZ7FagyvYvz87C6pYlJWmL2zbrTFkYh7IPmX-Qv9rPOfyp4uwhhbZZ731vfL1mSxuhh_p1dPVNFJJav4E8bZXyadg94EXJbqb3ecc_jQHWn1F_eiJsoVMSRdk%26nonce%3D636268234716844341.OTFhNGE1ZTEtNTMyYy00Y2MyLWFjOGMtMDE1NjBmNDY3ZGM1NWFmNzIxMjItYTgzZC00NjJhLTk4YWMtNDExOTA0N2I4MjNl%26x-client-SKU%3DID_NET%26x-client-ver%3D1.0.40306.1554`
This step takes place before redirecting back to your calling website, so I'm guessing you haven't implemented this page on IdSvr yet,
I have taken section 2 from a walkthrough on how to authorize with jwt so that I can get an access token from my client and authorize them to use the api. However, I can't seem to get this to work. I keep on getting a 401 message from Postman accompanied by a:
{
"Message": "Authorization has been denied for this request."
}
Tutorial Link: http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/
The access token comes from an authorization service I have created in Java, so the first section of the tutorial does not apply to me.
JWT
{
"exp": 1489641048,
"user_name": "testuser",
"authorities": [
"USER"
],
"jti": "2dde11c3-2f06-496c-9b36-4dbf71cdc2e2",
"client_id": "webreport_service",
"scope": [
"USER"
]
}
Web API code snippet
public void ConfigureOAuth(IAppBuilder app)
{
var audience = "webreport_service";
// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider("Any", "abc123")
}
});
}
It is slightly different from what is on the link in section 2, but that is because I don't base64 encode my secret and I also do not put the issuer in my jwt.
Postman
GET /api/protected HTTP/1.1
Host: localhost:54706
Authenticate: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0ODk2NDEyOTAsInVzZXJfbmFtZSI6InRlc3R1c2VyIiwiYXV0aG9yaXRpZXMiOlsiVVNFUiJdLCJqdGkiOiJlMDNkNWZmZC1hZWI4LTRkODctOGQ3My0zNjhjYjQ2ZDg2OWUiLCJjbGllbnRfaWQiOiJ3ZWJyZXBvcnRfc2VydmljZSIsInNjb3BlIjpbIlVTRVIiXX0.C4hivwA1VF-0GO0xCVUoDIheWQWlAcVWvAzChZTgrHY
Cache-Control: no-cache
Postman-Token: ff628109-d5f4-76e0-41c2-e0c7d377b93f
Any help would be greatly appreciated.
Thanks!
I think so check the following:
Firstly:
Check your secret base64 code. 'abc123' is true?
I'm check your token in jwt.io website on your secret code.
but Invalid Signature
Secondly:
Check your payload value.
What is 'iss' your jwt payload. / your issuer validate set 'Any'
What is 'aud' your jwt payload. / your audience validate set 'webreport_service'
Think about it.
Best regard