Looking to extract the expiration date from an x509 certificate?

I am currently engaged in a project that involves retrieving and displaying certificate information from an Azure integration account using Angular/Typescript. One of the requirements is to show the decoded public certificate to users to extract important details like the expiry date. I have tried using the atob() function to decode the certificate, but it seems ineffective. Is there a more straightforward way to achieve this with Angular/Typescript?

Here is an example of a certificate:

-----BEGIN CERTIFICATE-----
MIIDqDCCApCgAwIBAgICKg8wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCVVMx
EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxJDAiBgNVBAoT
G2dldGFDZXJ0IC0gd3d3LmdldA==

Below is a snippet of the code for reference:

Service

@Injectable()
export class integrationAccountService
{
  constructor(private httpclient: HttpClient, private api: ApiService) { }

  getcertificates(): Observable<Certificate> {
    const httpOptions : Object = {
      headers: new HttpHeaders({
        'Authorization': 'Bearer Token'
      }),
      responseType: 'json'
    };
    return this.httpclient.get<Certificate>(URL, httpOptions);
  }
}

Table Component

export class CertificateTableComponent {

  dataSource: MatTableDataSource<any>;
  //certificates: ValueEntity[] = [];
  data: CertificateRow[] = [];
  columns: string[] = ['name', 'id', 'type', 'publicCertificate'];

  @ViewChild(MatSort, { static: true }) sort: MatSort;
  @ViewChild(MatPaginator, { static:true }) paginator: MatPaginator;

  constructor(private _integrationAccountService: integrationAccountService, public dialog: MatDialog) {
  }

  ngOnInit() {

    this._integrationAccountService.getcertificates().subscribe(response => {
      //this.certificates = response.data;
      this.data = [];
      if (response.value) {
          for (let entity of response.value) {
              let row: CertificateRow = {
                  name: entity.name,
                  id: entity.id,
                  type: entity.type,
                  publicCertificate: entity.properties?.publicCertificate
              };
              this.data.push(row);
              console.log(atob(row.publicCertificate));
          }
      }

...</questionbody>
<exquestionbody>
<div class="question">
                
<p>I am working on a project to get and display certficate information from an azure integration account with angular/typescript. Part of the requirements is to display the decoded public certificate to a user to find useful information, i.e. expiry date. I have been trying to decode the certificate with the atob() function but it does not decode the certificate properly. Is there a simple way to do this with angular/typscript?</p>
<p>Here is an example of a certifcate:</p>
<pre><code>-----BEGIN CERTIFICATE-----
MIIDqDCCApCgAwIBAgICKg8wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCVVMx
EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxJDAiBgNVBAoT
G2dldGFDZXJ0IC0gd3d3LmdldGFjZXJ0LmNvbTAeFw0xOTExMDYwNjMwNDNaFw0y
...

For reference here is some of the code:

Service

@Injectable()
export class integrationAccountService
{
  constructor(private httpclient: HttpClient, private api: ApiService) { }

  getcertificates(): Observable<Certificate> {
    const httpOptions : Object = {
      headers: new HttpHeaders({
        'Authorization': 'Bearer Token'
      }),
      responseType: 'json'
    };
    return this.httpclient.get<Certificate>(URL, httpOptions);
  }
}

Table Component

export class CertificateTableComponent {

  dataSource: MatTableDataSource<any>;
  //certificates: ValueEntity[] = [];
  data: CertificateRow[] = [];
  columns: string[] = ['name', 'id', 'type', 'publicCertificate'];

  @ViewChild(MatSort, { static: true }) sort: MatSort;
  @ViewChild(MatPaginator, { static:true }) paginator: MatPaginator;

  constructor(private _integrationAccountService: integrationAccountService, public dialog: MatDialog) {
  }

  ngOnInit() {

    this._integrationAccountService.getcertificates().subscribe(response => {
      //this.certificates = response.data;
      this.data = [];
      if (response.value) {
          for (let entity of response.value) {
              let row: CertificateRow = {
                  name: entity.name,
                  id: entity.id,
                  type: entity.type,
                  publicCertificate: entity.properties?.publicCertificate
              };
              this.data.push(row);
              console.log(atob(row.publicCertificate));
          }
      }

      this.dataSource = new MatTableDataSource(this.data);
      this.dataSource.sort = this.sort;
      this.dataSource.paginator = this.paginator;

    })

  }
  applyFilter(event) {
    const filterValue = (event.target as HTMLInputElement).value;

    this.dataSource.filter = filterValue.trim().toLowerCase()
  }

  openDialog(publicCertificate) {
    let dialogRef = this.dialog.open(CertificateViewComponent, {
      data: {
        dialogCert: publicCertificate
      }

    });
  }
}

With this console.log(atob(row.certificate)); does not produce a decoded certifcate, it only displays the certificate as is returned from the api. Is there something I am missing here or another way to go about decoding the certificate?

Thanks in advance!

Answer №1

After some research, I was able to solve the issue by leveraging the capabilities of the node-forge library. Below is the snippet of code that helped me achieve the desired functionality in the table module:

import * as forge from 'node-forge';

declare var require: any
const pki = require('node-forge').pki;

const certPem = atob(entity.properties?.publicCertificate)
const cert = pki.certificateFromPem(certPem)

console.log(cert);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting problems with routing for an Angular 5 single page application when serving it from a Lumen 5.2 controller

I am facing an issue with serving an Angular SPA from a single routed Lumen endpoint. While the initial boot of the Angular application works fine when navigating directly to the endpoint, loading any child route of the Angular SPA does not work properly. ...

Tips on minimizing the vertical size of a mat field housing a mat-select dropdown

I need help reducing the height of a mat field that includes a mat-select in Angular v15. The code is directly from the material components documentation, with no alterations. It consists of a default table and default outline formfield. <mat-form-fi ...

The functionality of Angular Material Chip is encountering issues when paired with Angular 7

Issue with Angular Material Chip module compatibility in Angular version 7 Tech: Using Angular version 7, angular cli, and angular material Desired Outcome: Looking to successfully implement the angular material chip module Steps taken so far: Insta ...

Retrieve active route information from another component

We are utilizing a component (ka-cockpit-panel) that is not linked to any route and manually inserted into another component like so: .. ... <section class="ka-cockpit-panel cockpit-1 pull-left"> <ka-cockpit-panel></ka- ...

Angular 8 utilizes JavaScript for its programming language

Looking for a solution in JavaScript - check out: codepen.io/skovtun/pen/VwLvXPB Struggling to find an equivalent for Angular 8+. I want the center block to maintain a fixed width of 1200px, and automatically compress when the left, right, or both sideb ...

What sets apart TypeScript's indexed types from function signatures?

I am curious about the distinction between indexed type and function signatures in TypeScript. type A = { _(num: number): void; }['_']; type B = { _(ten: 10): void; }['_']; let a: A = (num) => { console.log(num); }; let b: B ...

What could be the reason for the malfunction of the loadingItem in PrimeNG's VirtualScroller

Currently, I have integrated PrimeNG 11.0.0-rc.2 with Angular 11 and am utilizing the VirtualScroller Component. However, I've encountered an issue where the loadingItem ng-template, designed to display a loader statement, is not functioning correctly ...

Lazy loading Angular component without route - Form control name has no value accessor

Exploring lazyloading a component without routing. I have two components, each with its own formGroup. The parent component, named vehicleForm, includes a FormControl named vehicleDetail. The child component's formGroup includes fields for fuel and ...

Extending the Object prototype within an ES6 module can lead to errors such as "Property not found on type 'Object'."

There are two modules in my project - mod1.ts and mod2.ts. //mod1.ts import {Test} from "./mod2"; //LINE X interface Object { GetFooAsString(): string; } Object.prototype.GetFooAsString = function () { return this.GetFoo().toString(); } //mod2. ...

What kind of Typescript type should be assigned to setState when passed to the component?

In my setup, I have a variety of Parent components: const ParentOne = () => { const [error, setError] = useState<{ one: boolean }>({ one: false }); ...omit return ( <> <Child setErr={setError} name={"one"} /> </> ...

Tips for creating a TypeScript function that can accept an array of concatenated modifiers with the correct data type

Can I modify data using a chain of function modifiers with correct typing in TypeScript? Is this achievable? const addA = (data: {}) => { return { ...data, a: "test" } } const addB = (data: {}) => { return { ...data, ...

Tips for maintaining type information when using generics in constructors

class Registry<Inst, Ctor extends new (...args: unknown[]) => Inst, T extends Readonly<Record<string, Ctor>>> { constructor(public records: T) { } getCtor<K extends keyof T>(key: K) { return this.records[key] } getIns ...

The process of automatically formatting Typescript has transformed into an unfortunate auto-discarding action

Typescript autoformatting has become a concerning issue. Whenever I input quoted strings (" or `), the code surrounding it seems to temporarily glitch, with other strings appearing as code. This problem has recently escalated, particularly with strings li ...

Creating a helper function for initiating and ending loading using Angular2's Observable forkJoin

I have a question regarding the forkjoin method in Angular. My main concern is writing a helper function that can handle multiple observables. This helper function should display a spinner service before subscribing to the observables and then hide the spi ...

When all the checkboxes have been checked and then one is unchecked, a row is consequently removed

In my Angular table, I have a checkbox column. When I check all checkboxes, they all get checked as expected. Similarly, when I uncheck all checkboxes, they all get unchecked properly. If I check just one checkbox, only that particular one gets checked, ...

Discover properties of a TypeScript class with an existing object

I am currently working on a project where I need to extract all the properties of a class from an object that is created as an instance of this class. My goal is to create a versatile admin page that can be used for any entity that is associated with it. ...

Tips for resolving aliases in tsconfig.app.json when dealing with multiple source directories in WebStorm

When it comes to generating source files, I do things a bit differently and create some of them outside of the usual src directory. Here's how my structure looks: - project - generated - $ui-services some-other.service.ts - src - ...

Using style binding and ngStyle doesn't appear to be effective for setting a background image within a DIV element in Angular5

After facing difficulties in customizing the spacing of Angular material cards, I decided to create my own cards. However, during this process, I encountered an issue where I needed to set an image as a background inside a div. Despite trying various CSS ...

Using TypeScript and the `this` keyword in SharePoint Framework with Vue

I'm currently developing a SharePoint Framework web part with Vue.js. Check out this code snippet: export default class MyWorkspaceTestWebPart extends BaseClientSideWebPart<IMyWorkspaceTestWebPartProps> { public uol_app; public render(): ...

What is the best way to utilize a React type as props for a custom component?

To make my component work properly, I am required to pass the inputmode as props from an external source. The acceptable values for <input inputMode=<valid values>> are outlined in the React types (node_modules@types\react\index.d.ts) ...