find onelogin login url - single-sign-on

I want to implement onelogin concpet.
I have application APP-A1 and it holds a link of another application APP-A2
When user has logged in my app APP-A1, when user click on link of APP-A2*
It should not ask for login again.
I found below url
https://developers.onelogin.com/saml/c-and-aspnet
I assume When user click on link of APP-A2 the below code should run and and redirect to idp_sso_target_url
using OneLogin.Saml;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
AccountSettings accountSettings = new AccountSettings();
OneLogin.Saml.AuthRequest req = new AuthRequest(new AppSettings(),
accountSettings);
Response.Redirect(accountSettings.idp_sso_target_url + "?SAMLRequest=" +
Server.UrlEncode(req.GetRequest(AuthRequest.AuthRequestFormat.Base64)));
}
}
public class AccountSettings
{
public string certificate = "-----BEGIN CERTIFICATE-----\nMIIBrTCCAaGgAwIBAgIBATADBg
EAMGcxCzAJBgNVBAYTAlVTMRMwEQYDAQQIDApD\nYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2Ex
ETAPBgNVBAoMCE9uZUxv\nZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMB4XDTEwMDMwOTA5NTgzNF
oX\nDTE1MDMwATA5NTgzNFowZzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju\naWExFTATBgNVBA
cMDFNhbnRhIE1vbmljYTERMA8GA1UECgwIT25lTG9naW4xGTAX\nBgNVBAMMEGFwcC5vbmVsA2dpbi5Ab20w
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ\nAoGBANtmwriqGBbZy5Dwy2CmJEtHEENVPoATCZP3UDESRDQmXy
9Q0Kq1lBt+KyV4\nkJNHYAAQ9egLGWQ8/1atkPBye5s9fxROtf8VO3uk/x/X5VSROEIrhFISGmKUnVXa\nUh
LFIXkGSCAIVfoR5S2ggdfpINKUWGsWS/lEzLNYMBkURXuVAgMBAAEwAwYBAAMB\nAA==\n-----END CERTI
FICATE-----";
public string idp_sso_target_url = "https://app.onelogin.com/saml/signon/12345";
}
Below code base should be there on APP-A2 page to authenticate the incoming response and allow user to login the application.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// replace with an instance of the users account.
AccountSettings accountSettings = new AccountSettings();
OneLogin.Saml.Response samlResponse = new Response(accountSettings);
samlResponse.LoadXmlFromBase64(Request.Form["SAMLResponse"]);
if (samlResponse.IsValid())
{
Response.Write("OK!");
Response.Write(samlResponse.GetNameID());
}
else
{
Response.Write("Failed");
}
}
}
If my assumption is correct where should I get the URL in developer account,
Thanks

At SAML there are 2 actors:
- Identity Providers. Where the users are authenticated.
- Service Providers. Protect the apps and redirect to the IdP when user want to log in the app.
In your case, you need to add SAML support to APP-A1 and APP-A2 (turning them Service Providers) and connect both to an Identity Provider.
Service Peoviders need to send an AuthNRequest (first code you mentioned) to the IdP SSO URL.
And also need to have an Assertion Consumer Service (SP ACS URL, second code you mentioned) in order to receive and process the SAMLResponse.
If you are using Onelogin as Identity Provider and have a a developer account you will be able to go to Apps>Add app and later look for a "SAML Test Connector"
On the "Configuration" section you should provide SP info and at the SSO section you get the IdP data... you may create one App connector per each SP. More info at
https://support.onelogin.com/hc/en-us/articles/202673944-How-to-Use-the-OneLogin-SAML-Test-Connector
IMPORTANT: The dotnet toolkit is a proof of concept, you should not use it in production as mentioned on the description of its github repository:
https://github.com/onelogin/dotnet-saml
Please use the alternatives mentioned there.

Related

Keycloak: have an Authenticator SPI "execution" available for clients flow

I implemented a custom Authenticator to restrict login above a given number of existing sessions.
This Authenticator implementation doesn't use any user interaction nor require any model change.
public class MaxGroupAttributeValAuthenticator implements Authenticator {
#Override
public void action(AuthenticationFlowContext authenticationFlowContext) {
if toManySessions(authenticationFlowContext){
authenticationFlowContext.cancelLogin();
} else {
authenticationFlowContext.success();
}
}
It only check the current number of session
This Authenticator is available as an "execution" to be added to a copy of the default Browser Flow
But on a copy of the default Clients Flow, my Custom SPI is not available in the execution list.
How can I have my clients calling this Authenticator upon login/session_creation ?

How to obtain a JWT token in Blazor code using OpenID Connect

Create a default Blazor server (not webassembly) application using windows identity platform as authorisation (I've used VS2022 / .net 6).
Is it possible to get hold of a JWT token in a code section of a blazor component (e.g. the LoginDisplay)?
For instance - I can get hold of the claims from the authentication state as follows (for my example in LoginDisplay.razor)
#code
{
[CascadingParameter] private Task<AuthenticationState> authenticationStateTask { get; set; }
protected override async Task OnInitializedAsync()
{
var authState = await authenticationStateTask;
var user = authState.User;
var identity = user.Identity as ClaimsIdentity;
if (identity != null)
{
IEnumerable<Claim> claims = identity.Claims;
// Can I get the a JWT Token signed by Azure B2C here?
}
}
}
Can I also get a JWT Token from the Azure service (I don't want to regenerate my own - I want an original one signed by microsoft).
As clarification - when using the MSAL javascript libraries on a different project (for a Single Page Application) I could do calls such as MSAL.acquireTokenSilent to get a token from the Azure B2C service for this purpose.
UPDATE - If HttpContext.GetTokenAsync returns null
In addition enets answer below. If you find that you can't access the JWT token using HttpContext.GetTokenAsync then see this question
You can access the access token and the refresh tokenas describe below, provided that you've set your app to use Jwt Token authentication (OpenID Connect). See this answer how to do that. Note: There is also a second answer related to that question by the same user. Search for it. This answer can also be useful. See this answer, which contains links to useful answers. Note: You can Google search string such as this: "enet stackoverflow blazor jwt token", and such like to find answers by me. If you want to see answers about the AuthenticationStateProvider, just search "enet stackoverflow blazor AuthenticationStateProvider"
Getting the access token
in _Host.cshtml you can code something like this:
#using Microsoft.AspNetCore.Authentication
#{
var tokens = new InitialApplicationState
{
AccessToken = await HttpContext.GetTokenAsync("access_token"),
RefreshToken = await HttpContext.GetTokenAsync("refresh_token")
};
}
And then pass the tokens object to your Blazor app like this:
<component type="typeof(App)" render-mode="ServerPrerendered" param-
InitialState="tokens"/>
Note that the tokens object is passed as a parameter to the App component, something like this:
#code{
[Parameter]
public InitialApplicationState InitialState { get; set; }
protected override Task OnInitializedAsync()
{
TokenProvider.AccessToken = InitialState.AccessToken;
TokenProvider.RefreshToken = InitialState.RefreshToken;
return base.OnInitializedAsync();
}
}
Note: TokenProvider is a singleton service instance that hold the JWT tokens, and make it available to other parts of your app. You can save the JWT tokens in the local storage or better the the session storage and read them when needed, etc.
Note: If you don't use Web Api, then you don't need Jwt token (authentication). Use Microsoft Identity authentication
To quote MS:
The built-in AuthenticationStateProvider service for Blazor Server apps obtains authentication state data from ASP.NET Core's HttpContext.User. This is how authentication state integrates with existing ASP.NET Core authentication mechanisms.
The Jwt token is in there as bearer.
To get the header there's a Question/Answer here by #enet that shows you how to access the HttpRequest from a Blazor Server App. - How to use the HttpContext object in server-side Blazor to retrieve information about the user, user agent.
I don't have a handy project which has JWT tokens to russle up some code for you. Someone else may be able to add another answer with code or add some to this.

Spring Security Authorize request from native Postman app

I am exploring/learning Spring security modules by implementing it through REST API.
To test the impact, we are using Postman native application as a rest client.
#RestController
#RequestMapping("/auth")
public class Employee {
#GetMapping("/status")
public ResponseEntity<String> getStatus()
{
ResponseEntity<String> responseEntity = new ResponseEntity<>("Resource is fetched", HttpStatus.OK);
return responseEntity;
}
}
above is a piece of resource for sake of consumption.
and below is the code snippet to configure Authentication and authorization
#EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("ashish").password("{noop}admin").roles("USER")
.and().withUser("foo").password("{noop}foo").roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/auth/status").hasRole("ADMIN").and()
.formLogin()
;
}
#Bean
public PasswordEncoder getPasswordEncoder()
{
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
now above authorization code is working fine when tried in browser - it uses its default spring login page.
however i am not quite able to understand how to execute/test the same through postman.
in method protected void configure(HttpSecurity http) , i tried removing formLogin() it did not work.
i added httpBasic - it also did not worked.
in postman, basic authentication is used by me.
while searching on internet, i came across some really good articles but almost all of them uses some sort of UI technology like angular or thymleaf to demonstrate the concept which i am finding hard to grasp.
I am referring below video tutorials to learn spring security.
https://www.youtube.com/watch?v=payxWrmF_0k&list=PLqq-6Pq4lTTYTEooakHchTGglSvkZAjnE&index=6&t=0s
Thanks in advance!
Ashish Parab
Do a GET request http://localhost:8080/login via postman and it will return you an html. Extract the _csrf token from the response. It will look like
<input name="_csrf" type="hidden"
value="1c470a6c-dff3-43aa-9d08-d308545dc880" />
Do a POST request as follows to http://localhost:8080/login, copying the _csrf token, username and password as form params
Take note of the JESSIONID Cookie value in the response from step two. And that is the session Id of the authenticated session.
As long as you sent the JESSIONID in subsequent requests as a cookie, spring security knows who you are. Postman will add that Cookie automatically to subsequent requests.
you can add it manually as header with that cookie header or update the postman settings to always send JESSIONID cookie
You will have to implement JWT token for the same and add it to the request header 'Authorization' in Postman. You can take a look at Java Brains Spring security videos on youtube.

IdentityServer4 how to redirect the flow after login

I have installed an IdentityServer4 and a Client (Hybrid Mvc Client). All is ok. The following flow works:
1. User call secure page PageX (the controller is protected with Authorize attribute)
2. than system redirects the flow to Login page on IdentityServer
3. After authentication/authorization the IdentityServer redirect the user to url defined (redirect_uri) in the client configuration (page named Home) .
Now i don't know how to implement at the step 3 the redirection to PageX, the original page requested.
I have to create a custom AuthorizeAttribute to save on session storage the url of PageX and than using it in callback page? or is there any configuration on IdentityServer or client that could help me?
Thanks in advance
This is typically what you’d use the state parameter for. Your callback will receive the state value back unaltered and then you can verify the URL within is local and redirect to it automatically.
I’d recommend protecting the value from tampering using the DataProtection features in .net.
After successful login, by default the IdentityServer middleware tries to redirect to a consent page where to inform the user for the "allowed scopes". In this page are shown the claims that the client mvc site will receive access to: user identifier, user profile, email etc.
If you didn't setup such, you may set: "RequireConsent = false" when you define your MVC client. In such scenario the IdentityServer will redirect back to "RedirectUris" without showing consent page.
Example:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "mvc",
ClientName = "mvc Client",
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email
},
RequireConsent = false
}
};
}
The other thing that I've noticed in the IdentityServer4 demos and quick starts is that you need the following NuGet packages:
For client website:
IdentityModel,
Microsoft.AspNetCore.All
For IdentityServer Authentication app:
IdentityServer4,
IdentityServer4.AccessTokenValidation,
IdentityServer4.AspNetIdentity,
Microsoft.AspNetCore.All
You may install these packages just to get the demo working.

IdentityServer SSO - Trusted application

I need to SSO (single sign on) a user coming from an application of mine (identity provider using ASPNET Session State) and redirect them to another application of mine (service provider) that is configured to use implicit flow with IdentityServer4. I need to achieve this without requiring the user to log back in and without providing the user's password.
My initial thought was that I could use a client secret for the identity provider to redirect the user to the IdentityServer4 authentication end point with the access token as a query parameter and then use a custom validator or extension grant to issue an identity token for use with the service provider application without needing to also provide the user's password.
I've managed to issue an access token to the identity provider and then redirect the user to IdentityServer4, but issuing an identity token has proven difficult for me. I've poured over the samples and documentation and I'm confused to say the least.
I'm looking for direction on the appropriate approach to this scenario and perhaps a comprehensive example in C#. I've come to understand I can use a hybrid flow to issue an access token as well as an identity token. I think my biggest struggle is how to redirect the user and, based on the access token, issue the user an identity token (and if this is even an acceptable approach).
Simply put: I'd like to redirect the user from Application A to IdentityServer4 to Application B based on trust with the identity provider (via client secret?).
Note: I understand this could be considered an opinion-based question, but based on my research I believe there is one single best practice and that's what I'm asking for.
I managed to get this working by the following flow:
Authorize the user in Application A (Identity Provider)
Obtain Access Token from Identity Server 4 via Token Endpoint and shared secret.
Add access token as a query string parameter since headers are not preserved on redirect.
Redirect the user to an Account controller method that accepts identifying information such as username. This method is protected by a custom middleware class that checks the query string for an access token parameter. If the token exists, it is added to the authentication header; this authorizes the user to hit this controller method.
The controller method will then sign the user in and redirect them to the /connect/authorize/login endpoint.
Finally, the login endpoint sets the cookie and redirects the user to Application B (Service Provider), whose URL is specified via the redirect_uri query parameter.
Configuration for shared secret:
Add appropriate grant type, secret and new scope name to the client. The new scope will help in debugging Access token issues in your logs (especially if you have multiple applications hitting your ID4 server). Also make sure to add the Service Provider's URL to the client RedirectUris, otherwise you'll receive an "invalid redirect" error.
AllowedGrantTypes = new List<string> { GrantType.Implicit, GrantType.ClientCredentials },
ClientSecrets = new List<Secret> {
new Secret(_clientSecrets.ExternalIdpSecret.Sha256(), clientID)
},
AllowedScopes = new List<string>
{
"newScopeName"
},
RedirectUris = new List<string>
{
$"http://localhost:<portnumber>"
}
Next, add your custom middleware.
public class QueryStringOAuthBearerMiddleware
{
private readonly RequestDelegate next;
public QueryStringOAuthBearerMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
this.BeginInvoke(context);
await this.next.Invoke(context);
this.EndInvoke(context);
}
private void BeginInvoke(HttpContext context)
{
if (context.Request.Query.ContainsKey("accesstokenparametername"))
{
var accessToken = context.Request.Query.First(p => p.Key == "accesstokenparametername");
if (!string.IsNullOrEmpty(accessToken.Value))
{
context.Request.Headers.Add("Authorization", "Bearer " + accessToken.Value);
}
}
}
private void EndInvoke(HttpContext context)
{
}
}
And add the middleware to your configuration.
app.UseMiddleware<QueryStringOAuthBearerMiddleware>();
Create your login method.
[HttpGet]
[Authorize]
public async Task<IActionResult> Login2(string userName, string returnURL)
{
await _httpContextWrapper.SignInAsync(userName);
return Redirect(returnURL);
}
Configuration for Client application (IDP):
Your client side code should look like this:
var disco = await DiscoveryClient.GetAsync("http://localhost:<portnumber>");
var tokenClient = new TokenClient(disco.TokenEndpoint, "clientIdentifier", "IUsedAGuidHere");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("newScopeName");
var redirectURL = string.Format("http://localhost:2228/account/Login2?userName=<UserIDValue>&returnURL={1}&accesstokenparametername={0}",
tokenResponse.AccessToken,
Server.UrlEncode(
string.Format("/connect/authorize/login?client_id={3}&redirect_uri={2}&response_type=id_token%20token&scope=<ImplicitFlowScopes>&state={0}&nonce={1}",
CryptoRandom.CreateUniqueId(),
CryptoRandom.CreateUniqueId(),
Server.UrlEncode("http://localhost:<PortNumber>"),
"ClientIdentifier")));
Response.Redirect(redirectURL, false);
Note: Please understand you won't be able to take this code AS-IS and make it work. I've heavily modified it to protect the security of my resources.
I think I might take care of the Authentication with Application A first, then forward on to the next app...
Application A --> IdentityServer --> Application A --> Application B.
You could include some custom parameters in your returnUrl which Application A could read upon return from IdentityServer that would trigger the redirect to Application B.