Skip to content

Instantly share code, notes, and snippets.

@johlju
Created November 20, 2024 15:20
Show Gist options
  • Save johlju/f110b0c4bb060b2c11f31f3e87ea9bb2 to your computer and use it in GitHub Desktop.
Save johlju/f110b0c4bb060b2c11f31f3e87ea9bb2 to your computer and use it in GitHub Desktop.
Temp - CustomSecurityExtension

PROMPT: Jag vill använda en Identity Provider för att autentisera och få åtkomst till en on-premises PowerBI Reporting Services. Hur ska man göra konfigurationen för PowerBI Reporting Services för att kunna autentisera mot en Identity Provider?

För att konfigurera Power BI Reporting Services (on-premises) att autentisera mot en Identity Provider behöver du implementera en anpassad säkerhetsförlängning (custom security extension). Som standard använder Reporting Services Windows-autentisering, men genom att skapa en anpassad säkerhetsförlängning kan du integrera andra autentiseringsmetoder, inklusive externa Identity Providers.

Här är stegen för att göra detta:

  1. Förstå Kraven: Se till att din Identity Provider stöder standardautentiseringsprotokoll som SAML, OAuth eller OpenID Connect.

  2. Utveckla en Anpassad Säkerhetsförlängning:

    • Skapa en .NET-assembly som implementerar IAuthenticationExtension-gränssnittet från Reporting Services.
    • Implementera metoder för autentisering, auktorisation och hantering av användarsessioner.
    • Integrera din förlängning med Identity Providern genom att implementera nödvändiga autentiseringsflöden.
  3. Konfigurera Reporting Services:

    • Placera din anpassade säkerhetsförlängnings-assembly i Reporting Services bin-katalog (\Reporting Services\ReportServer\bin).
    • Uppdatera konfigurationsfilerna:
      • RSReportServer.config: Ändra <Authentication>-elementet för att använda din anpassade säkerhetsförlängning.
      • RSSrvPolicy.config: Definiera säkerhetspolicyn för din förlängning.
  4. Anpassa Web.config för Web Portal:

    • Om det behövs, uppdatera Web.config-filen för att inkludera nödvändiga inställningar för din Identity Provider (t.ex. endpoint-URL:er, klient-ID:n).
  5. Testa Integrationen:

    • Starta om Reporting Services-tjänsten.
    • Verifiera att autentisering och auktorisation fungerar som förväntat genom att logga in och komma åt rapporter.
  6. Underhåll och Support:

    • Dokumentera din implementation för framtida underhåll.
    • Håll dig uppdaterad med eventuella ändringar i Identity Providerns API eller autentiseringsmetoder.

Viktiga Tips:

  • Säkerhet: Se till att all kommunikation med Identity Providern är säker, använd HTTPS och följ bästa praxis för hantering av tokens och känslig information.
  • Felhantering: Implementera robust felhantering och loggning för att underlätta felsökning.
  • Testning: Utför omfattande tester i en utvecklings- eller testmiljö innan du implementerar förändringarna i produktion.

Referenser:

Om du behöver ytterligare hjälp eller har frågor om specifika steg i processen, tveka inte att fråga!

PROMPT: Please create a custom security extension that will connect and receive a token from PhenixID using either SAML or OpenIDConnect depending on which is easiest.

Certainly! I'll guide you through the process of creating a custom security extension for Power BI Reporting Services that connects to PhenixID using OpenID Connect. OpenID Connect is generally easier to implement than SAML, especially with .NET, due to better library support.


Overview

  • Goal: Authenticate users in Power BI Reporting Services using PhenixID via OpenID Connect.
  • Approach: Develop a custom security extension implementing IAuthenticationExtension2 and configure it to use OpenID Connect for authentication.

Prerequisites

  • Development Environment:
    • Visual Studio installed.
    • .NET Framework knowledge, especially in C#.
  • Access to:
    • PhenixID client credentials (Client ID and Client Secret).
    • PhenixID endpoints (Authorization, Token, UserInfo).

Step 1: Set Up the Project

  1. Create a New Class Library Project:

    • Open Visual Studio.
    • Create a new Class Library project targeting the .NET Framework version compatible with your Reporting Services.
  2. Add References:

    • Add references to Reporting Services assemblies, typically located in the Reporting Services installation directory:

      • Microsoft.ReportingServices.Interfaces.dll
      • Microsoft.ReportingServices.Diagnostics.dll
  3. Install NuGet Packages:

    • Install packages to handle OpenID Connect and JWT tokens:

      Install-Package Microsoft.IdentityModel.Protocols.OpenIdConnect
      Install-Package System.IdentityModel.Tokens.Jwt
      Install-Package Microsoft.Owin.Security.OpenIdConnect

Step 2: Implement the Custom Security Extension

  1. Implement IAuthenticationExtension2:

    • Create a class that implements IAuthenticationExtension2.

    • Implement required methods:

      • LogonUser
      • GetUserInfo
      • IsValidPrincipalName
      • GetUserPrincipal
    • Since OpenID Connect uses tokens, you'll focus on handling the token rather than traditional username/password authentication.

  2. Sample Implementation:

    using System;
    using System.Security.Principal;
    using Microsoft.ReportingServices.Interfaces;
    
    public class OpenIdConnectSecurityExtension : IAuthenticationExtension2
    {
        public void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)
        {
            var context = System.Web.HttpContext.Current;
            if (context != null && context.User != null)
            {
                userIdentity = context.User.Identity;
                userId = IntPtr.Zero;
            }
            else
            {
                userIdentity = null;
                userId = IntPtr.Zero;
            }
        }
    
        public bool IsValidPrincipalName(string principalName)
        {
            return !string.IsNullOrEmpty(principalName);
        }
    
        public IPrincipal GetUserPrincipal(string userName)
        {
            return new GenericPrincipal(new GenericIdentity(userName), null);
        }
    
        // Other methods...
    }

Step 3: Handle OpenID Connect Authentication

  1. Create an HTTP Module:

    • Since Reporting Services doesn't natively support OpenID Connect, use an HTTP module to intercept requests and manage authentication flow.
  2. Implement the HTTP Module:

    using System;
    using System.Web;
    using Microsoft.IdentityModel.Protocols.OpenIdConnect;
    using Microsoft.IdentityModel.Protocols;
    using System.Threading;
    using System.IdentityModel.Tokens.Jwt;
    using System.Security.Claims;
    
    public class OpenIdConnectAuthenticationModule : IHttpModule
    {
        private static OpenIdConnectConfiguration _configuration;
    
        public void Init(HttpApplication context)
        {
            context.AuthenticateRequest += OnAuthenticateRequest;
            LoadConfiguration();
        }
    
        private async void LoadConfiguration()
        {
            var issuer = "https://phenixid.example.com";
            var manager = new ConfigurationManager<OpenIdConnectConfiguration>(
                $"{issuer}/.well-known/openid-configuration",
                new OpenIdConnectConfigurationRetriever()
            );
            _configuration = await manager.GetConfigurationAsync(CancellationToken.None);
        }
    
        private void OnAuthenticateRequest(object sender, EventArgs e)
        {
            var context = ((HttpApplication)sender).Context;
            var request = context.Request;
            var response = context.Response;
    
            if (context.User == null || !context.User.Identity.IsAuthenticated)
            {
                var token = request.QueryString["id_token"];
                if (!string.IsNullOrEmpty(token))
                {
                    var principal = ValidateToken(token);
                    if (principal != null)
                    {
                        context.User = principal;
                    }
                    else
                    {
                        RedirectToIdentityProvider(response);
                    }
                }
                else
                {
                    RedirectToIdentityProvider(response);
                }
            }
        }
    
        private ClaimsPrincipal ValidateToken(string token)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var validationParameters = new TokenValidationParameters
            {
                ValidIssuer = _configuration.Issuer,
                ValidAudiences = new[] { "your-client-id" },
                IssuerSigningKeys = _configuration.SigningKeys
            };
    
            try
            {
                var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
                return principal;
            }
            catch
            {
                return null;
            }
        }
    
        private void RedirectToIdentityProvider(HttpResponse response)
        {
            var redirectUri = HttpUtility.UrlEncode("https://your-reportserver-url/");
            var authorizationEndpoint = _configuration.AuthorizationEndpoint;
            var clientId = "your-client-id";
    
            var authorizationUrl = $"{authorizationEndpoint}?client_id={clientId}&response_type=id_token&scope=openid&redirect_uri={redirectUri}&nonce={Guid.NewGuid()}";
    
            response.Redirect(authorizationUrl);
        }
    
        public void Dispose() { }
    }
  3. Configure the Module in Web.config:

    • In the Web.config file of your Report Server, register the HTTP module:

      <configuration>
        <system.web>
          <httpModules>
            <add name="OpenIdConnectAuthenticationModule" type="YourNamespace.OpenIdConnectAuthenticationModule, YourAssemblyName"/>
          </httpModules>
        </system.web>
      </configuration>
    • For IIS 7 and above, also add under <system.webServer>:

      <system.webServer>
        <modules>
          <add name="OpenIdConnectAuthenticationModule" type="YourNamespace.OpenIdConnectAuthenticationModule, YourAssemblyName" />
        </modules>
      </system.webServer>

Step 4: Configure Reporting Services

  1. Deploy the Assembly:

    • Copy your compiled DLL (YourAssemblyName.dll) to the Reporting Services bin directory:

      C:\Program Files\Microsoft Power BI Report Server\PBIRS\ReportServer\bin
      
  2. Modify RSReportServer.config:

    • Locate and modify the <Authentication> element:

      <Authentication>
        <Extension Name="OpenIdConnectSecurityExtension" Type="YourNamespace.OpenIdConnectSecurityExtension, YourAssemblyName"/>
      </Authentication>
  3. Update RSSrvPolicy.config:

    • Ensure your assembly has the necessary code access security permissions.

      <CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust">
        <IMembershipCondition class="StrongNameMembershipCondition" version="1"
          PublicKeyBlob="YourPublicKeyBlob"
          Name="YourAssemblyName"
          AssemblyVersion="1.0.0.0"/>
      </CodeGroup>

Step 5: Configure PhenixID

  1. Register Your Application:

    • In PhenixID administration, register a new client application.
    • Set the Client ID and Client Secret.
    • Define the Redirect URI to point to your Report Server URL.
  2. Gather OpenID Connect Endpoints:

    • Obtain the Authorization Endpoint, Token Endpoint, and UserInfo Endpoint from PhenixID.

Step 6: Final Configuration and Testing

  1. Restart Services:

    • Restart the Power BI Report Server service to apply changes.
  2. Test the Authentication Flow:

    • Navigate to the Report Server URL.
    • You should be redirected to the PhenixID login page.
    • After logging in, you should be redirected back with access to the reports.

Additional Tips

  • Error Handling:

    • Implement proper exception handling and logging in your HTTP module and security extension for easier troubleshooting.
  • HTTPS Configuration:

    • Ensure all communications are over HTTPS to secure token exchanges.
  • Session Management:

    • Consider implementing session handling to maintain user state without re-authenticating on each request.
  • Token Refresh:

    • Implement token refresh logic if PhenixID provides refresh tokens, to maintain long-lived sessions.

Sample Code Repository

  • While I can't provide an actual repository, you can refer to Microsoft's sample on GitHub for creating custom security extensions:


References


Note: Custom security extensions can be complex and may impact the stability and security of your Reporting Services. It's highly recommended to thoroughly test in a non-production environment before deploying to production.


If you need further clarification on any step or assistance with specific code implementations, feel free to ask!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment