Skip to content

Commit

Permalink
Merge pull request #4907 from sagara-gunathunga/angular
Browse files Browse the repository at this point in the history
Adding Angular complete guide
  • Loading branch information
himeshsiriwardana authored Dec 3, 2024
2 parents edb59ae + 3af15ca commit 558693b
Show file tree
Hide file tree
Showing 18 changed files with 683 additions and 3 deletions.
109 changes: 109 additions & 0 deletions en/asgardeo/docs/complete-guides/angular/accessing-protected-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
template: templates/complete-guide.html
heading: Accessing protected API from your Angular app
read_time: 2 min
---

We’ve covered most of the key activities for adding user login to your Angular app. To recap, during user login, the Angular OAuth2 OIDC SDK provides both an ID token and an access token. We’ve been using the ID token in the previous sections to establish the logged-in user context and enable secure access. In this section, we’ll focus on how to call a secure API from your Angular app using the other token—the access token.

For simplicity, let's assume that the APIs we’re calling are secured by the same Identity Provider (IdP) and use the same issuer— in this case, the same Asgardeo organization. This is typical when Angular apps are interacting with internal APIs within the same organization. However, if your app needs to call APIs secured by a different IdP, you’ll need to exchange your current access token for a new one issued by the IdP securing those APIs. This can be done using the OAuth2 token exchange grant type or other supported grant types. We will cover these scenarios in a separate guide.

## Using SDK Built-in HTTP client

You can utilize Angular's `HttpClient` to make HTTP requests to secure endpoints. You don't need to manually attach the access token to requests if you use the Angular OAuth2 OIDC SDK correctly, as it will handle that automatically.
The following is a simple example of how you might use the Angular OAuth2 OIDC SDK’s `HttpClient` to call a protected API endpoint, such as `/scim2/me` (to get the user profile details after signing in). In this case, the SCIM 2 endpoint is secured by the same Asgardeo organization. Asgardeo provides a SCIM 2 API for managing users within your organization. While user management with SCIM 2 is a topic for a different guide, we will use the API as part of our current guide.

### Step 1: Import Required Modules

Update the `app.config.ts` file as follows to configure the allowed URLs and include the access token in API requests. Ensure you refer to the domains of your API server under `allowedUrls` and set `sendAccessToken` to `true` so that the access token is included in the requests made to these endpoints:


```javascript title="src/main.jsx" hl_lines="5-11"
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes),
provideHttpClient(withInterceptorsFromDi()),
provideOAuthClient({
resourceServer: {
allowedUrls: ['https://api.asgardeo.io'],
sendAccessToken: true
}
}),
{
provide: APP_INITIALIZER,
useFactory: initializeOAuth,
deps: [OAuthService],
multi: true
}
]
};

```


### Step 2: Make HTTP Requests

In your component, you can use Angular's `HttpClient` to call secure APIs. Here's how to do it:

```javascript title="src/main.jsx" hl_lines="16"

import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
selector: 'app-dashboard',
standalone: true,
imports: [],
templateUrl: './dashboard.component.html',
styleUrl: './dashboard.component.css'
})
export class DashboardComponent {
private http = inject(HttpClient);
data: any;

constructor() {
this.http.get('https://api.asgardeo.io/t/mifrazmurthaja/scim2/Me')
.subscribe(response => this.data = response);
}
}


```

In the above code, the access token is automatically attached to the `Authorization` header by the Angular OAuth2 OIDC SDK when you make requests to the specified allowed URLs.


## Manually Managing Access Tokens in API Requests

If you are not using the built-in access token management, you can manually fetch the access token and attach it to your requests. Here’s how to do that:


```javascript title="src/main.jsx"

import { Component, inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { OAuthService } from 'angular-oauth2-oidc';

@Component({
selector: 'app-dashboard',
standalone: true,
imports: [],
templateUrl: './dashboard.component.html',
styleUrl: './dashboard.component.css'
})
export class DashboardComponent {
private http = inject(HttpClient);
data: any;

constructor(private oAuthService : OAuthService) {
const token = this.oAuthService.getAccessToken();
const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`);
this.http.get('https://api.asgardeo.io/t/mifrazmurthaja/scim2/Me', { headers })
.subscribe(response => this.data = response);
}
}



```
99 changes: 99 additions & 0 deletions en/asgardeo/docs/complete-guides/angular/add-login-and-logout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
template: templates/complete-guide.html
heading: Add login and logout to your app
read_time: 2 min
---

Next, let's add login and logout features to your Angular app. Angular uses services to access authentication data, and we can inject the `OAuthService` into your components to manage user authentication. The `OAuthService` provides methods for logging in and out, checking the user's authentication status, and retrieving access tokens. The key methods you will use are `initLoginFlow()` for signing in and `revokeTokenAndLogout()` for signing out. You can use these methods directly within your Angular components to trigger login and logout actions.

Replace the existing content of the `app.component.ts` file with following content.

!!! tip
For better organization, you can create separate components for different purposes, such as login and home pages. However, for simplicity, we are using the default component in this example.

```javascript title="app.component.ts" hl_lines="16-28"

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';
import { CommonModule } from '@angular/common';

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, CommonModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})

export class AppComponent {
title = 'asgardeo-angular';
isAuthorized = this.oAuthService.hasValidAccessToken();

constructor(private oAuthService: OAuthService) {

}

login() {
this.oAuthService.initLoginFlow();
}

logout() {
this.oAuthService.revokeTokenAndLogout();
}
}

```

Once you've defined these methods in app.component.ts, update the corresponding HTML template in app.component.html by modifying the lines below:

```html title="app.component.html"

<button *ngIf="!isAuthorized" (click)="login()">Login</button>

<button *ngIf="isAuthorized" (click)="logout()">Logout</button>

```

Let’s look into the underlying details of what’s happening here.

The `AppComponent` leverages the `OAuthService`, which was initialized earlier in the `ApplicationConfig` using `authConfig`, to access various methods and attributes provided by the SDK, such as `initLoginFlow()`, `revokeTokenAndLogout()`, and user-specific attributes. The `AppComponent` defines its own methods, like `login()` and `logout()`, which make use of these SDK methods.

In `app.component.html`, these methods are tied to button click events. The template also dynamically renders content based on the user's authentication status. It checks for the presence of the username attribute in the session to determine if the user is authenticated. If username is available, indicating that the user is logged in, the "Logout" button is displayed and triggers the `logout()` method. Otherwise, the "Login" button is shown, which initiates the login process via `login()`.

Save the changes and re-run the application.

```bash
ng serve

```

Visit your app's homepage at [http://localhost:4200](http://localhost:4200).


## Initiate Sign In
Clicking on the login button will initiate an OIDC request. You can observe this authorization request in the browser's DevTools. To do so, right-click on the application, click "Inspect," switch to the "Network" tab, and in the filter input, type "authorize." Then, click on the Login button to see the details of the request.

![OIDC request]({{base_path}}/complete-guides/angular/assets/img/image15.png){: width="800" style="display: block; margin: 0;"}

!!! tip "Tip"

The OpenID Connect specification offers several functions, known as grant types, to obtain an access token in exchange for user credentials. This example uses the authorization code grant type. In this process, the app first requests a unique code from the authentication server, which can later be used to obtain an access token. For more details on the authorization code grant type, please refer to the [Asgardeo documentation.](https://wso2.com/asgardeo/docs/guides/authentication/oidc/implement-auth-code-with-pkce/){:target="_blank"}

Asgardeo will receive this authorization request and respond by redirecting the user to a login page to enter their credentials.

![OIDC request]({{base_path}}/complete-guides/angular/assets/img/image16.png){: width="800" style="display: block; margin: 0;"}

At this stage, **you need to create a [test user in Asgardeo](https://wso2.com/asgardeo/docs/guides/users/manage-users/#onboard-users){:target="_blank"} to try out the application.** Once you create a test user, you can enter the username and password of the test user to the login screen.

!!! tip "Tip"

**PKCE (Proof Key for Code Exchange)** is an addition to the OAuth2 specification to make the authorization code more immune to replay attacks. It is enabled by default for public clients such as our single page Angular app.

If you want to disable PKCE for some reason, you can do so via following the steps below. **However, disabling PKCE for public clients such as our single page Angular app is highly discouraged.**

1. Log in to the {{product_name}} console and select the application you created.
2. Switch to the Protocol tab.
3. Uncheck the Mandatory checkbox under PKCE section.

In this section, we have added login and logout features to our Angular app. In the next step, we will look into how to access the user attributes of the logged in user.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions en/asgardeo/docs/complete-guides/angular/create-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
template: templates/complete-guide.html
heading: Create an Angular app
read_time: 2 min
---

For this guide, you will be creating a simple Angular app using Angular CLI, the official tool provided by Angular to simplify project scaffolding and development.

!!! note

The Angular OAuth2 OIDC SDK supports only up to Angular CLI version 17. Therefore, we are creating this application using Angular CLI version 17.


Open a terminal, change the directory to where you want to initialize the project, and run the following command to create your first Angular sample application


```bash
npm install -g @angular/cli@17

ng new asgardeo-angular
```

Running this command will create a folder with a ready-made Angular application.

Once the application is created, install the necessary dependencies using the following command:


```bash

cd asgardeo-angular

npm install
```

Then run the sample in the development mode. This allows you to see real-time updates and debug the app as you make changes.

```bash
ng serve
```

By default, the development server will run on the port 4200. You can navigate to [http://localhost:4200](http://localhost:4200){:target="_blank"} in your browser, and you should see the sample application working as expected.

![Navigate to localhost]({{base_path}}/complete-guides/angular/assets/img/image6.png){: width="600" style="display: block; margin: 0;"}

At this point, you have a simple yet fully functional Angular app. In the next step, let’s try to integrate an authentication SDK with the app.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
template: templates/complete-guide.html
heading: Display logged-in user details
read_time: 2 min
---

At this point, we’ve successfully implemented login and logout capabilities by integrating your Angular app with {{product_name}}. The next step is to access and display the logged-in user details within the application. The SDK provides a way to retrieve the authenticated user’s basic information.

To do this, you can leverage the `getIdentityClaims` method to fetch the user’s profile information. The following code example demonstrates how to access and display the user's profile information in your Angular component.

Add the `username()` function to the `app.component.ts` file to access the username attribute.

```javascript title="app.component.ts"


get username() {
var claims = this.oAuthService.getIdentityClaims();
if (!claims) return null;
return claims['username'];
}


```


Next, modify the `app.component.html` file with the following code.

```html title="app.component.html" hl_lines="2"

<button *ngIf="!isAuthorized" (click)="login()">Login</button>
<h1 *ngIf="username">Hello {{ username }}!</h1>
<button *ngIf="isAuthorized" (click)="logout()">Logout</button>

```


## Getting additional user attributes

In the above code, we have rendered only the username of the logged-in user. Similarly, you can access other user attributes, such as given_name and and country. The following code snippet illustrates how to access these attributes in your app. The Angular OAuth2 OIDC SDK is responsible for processing the ID token and decoding these attributes.

1. Log in to the {{product_name}} console and select the application you created.
2. Go to the **User Attributes** tab.
3. Select the **given_name** attribute.
4. Click Update to save the changes.

Add the `username()` function to the `app.component.ts` file to access the username attribute.

```javascript title="app.component.ts" hl_lines="7-11"
get username() {
var claims = this.oAuthService.getIdentityClaims();
if (!claims) return null;
return claims['username'];
}

get givenName() {
var claims = this.oAuthService.getIdentityClaims();
if (!claims) return null;
return claims['given_name'];
}

```


Now, we can display the given_name attribute by modify the `app.component.html` file with the following code.

```html title="app.component.html" hl_lines="3"

<button *ngIf="!isAuthorized" (click)="login()">Login</button>
<h1 *ngIf="username">Hello {{ username }}!</h1>
<h1 *ngIf="givenName">Your given name : {{ givenName }}!</h1>
<button *ngIf="isAuthorized" (click)="logout()">Logout</button>

```


In this step, we further improved our Angular app to display the user attributes. As the next step, we will try to secure routes within the app.
Loading

0 comments on commit 558693b

Please sign in to comment.