diff --git a/articles/api/authentication/api-authz/_get-token.md b/articles/api/authentication/api-authz/_get-token.md index 8f0dc5a9f9..9738635486 100644 --- a/articles/api/authentication/api-authz/_get-token.md +++ b/articles/api/authentication/api-authz/_get-token.md @@ -438,7 +438,7 @@ Content-Type: application/json ``` ```JSON -HTTP/1.1 400 BAD REQUEST +HTTP/1.1 403 Forbidden Content-Type: application/json { // Can be retried @@ -448,7 +448,7 @@ Content-Type: application/json ``` ```JSON -HTTP/1.1 400 BAD REQUEST +HTTP/1.1 429 Too Many Requests Content-Type: application/json { // Can be retried @@ -458,7 +458,7 @@ Content-Type: application/json ``` ```JSON -HTTP/1.1 400 BAD REQUEST +HTTP/1.1 403 Forbidden Content-Type: application/json { // Cannot be retried; transaction failed diff --git a/articles/flows/guides/device-auth/includes/request-tokens.md b/articles/flows/guides/device-auth/includes/request-tokens.md index f8858f5257..d2b1de6a53 100644 --- a/articles/flows/guides/device-auth/includes/request-tokens.md +++ b/articles/flows/guides/device-auth/includes/request-tokens.md @@ -50,6 +50,8 @@ While you wait for the user to authorize the device, you may receive a few diffe You will see this error while waiting for the user to take action. Continue polling using the suggested interval retrieved in the previous step of this tutorial. ```json +`HTTP 403` + { "error": "authorization_pending", "error_description": "..." @@ -61,6 +63,8 @@ You will see this error while waiting for the user to take action. Continue poll You are polling too fast. Slow down and use the suggested interval retrieved in the previous step of this tutorial. To avoid receiving this error due to network latency, you should start counting each interval after receipt of the last polling request's response. ```json +`HTTP 429` + { "error": "slow_down", "error_description": "..." @@ -76,6 +80,8 @@ Then `expired_token` error will be returned exactly once; after that, the dreade ::: ```json +`HTTP 403` + { "error": "expired_token", "error_description": "..." @@ -87,6 +93,8 @@ Then `expired_token` error will be returned exactly once; after that, the dreade Finally, if access is denied, you will receive: ```json +`HTTP 403` + { "error": "access_denied", "error_description": "..." diff --git a/articles/microsites/call-api/call-api-m2m-app.md b/articles/microsites/call-api/call-api-m2m-app.md index 51dcd34287..5f8d1154f5 100644 --- a/articles/microsites/call-api/call-api-m2m-app.md +++ b/articles/microsites/call-api/call-api-m2m-app.md @@ -3,6 +3,7 @@ title: Call Your API from a Machine-to-Machine App description: Everything you need to know to call your API from your machine-to-machine (M2M) app ctaText: Go to Quickstart ctaLink: /docs/quickstart/backend +public: false template: microsite topics: - authentication diff --git a/articles/quickstart/backend/aspnet-core-webapi/index.yml b/articles/quickstart/backend/aspnet-core-webapi/index.yml index f8b4bb23dc..146f711734 100644 --- a/articles/quickstart/backend/aspnet-core-webapi/index.yml +++ b/articles/quickstart/backend/aspnet-core-webapi/index.yml @@ -1,7 +1,7 @@ title: ASP.NET Core Web API # TODO remove 'image' once new QS page is live. Then only use 'logo'. image: /media/platforms/asp.png -logo: dotnet +logo: dotnet-platform alias: - asp.net core webapi - aspnet core webapi diff --git a/articles/quickstart/backend/java-spring-security5/01-authorization.md b/articles/quickstart/backend/java-spring-security5/01-authorization.md index 2b6fb145ea..fa3cf07bb4 100644 --- a/articles/quickstart/backend/java-spring-security5/01-authorization.md +++ b/articles/quickstart/backend/java-spring-security5/01-authorization.md @@ -1,7 +1,7 @@ --- title: Authorization -name: How to secure your API using Spring Security 5 and Auth0 -description: This tutorial demonstrates how to add authorization to an API using Spring Security 5. +name: How to secure your API with Spring Boot +description: This tutorial demonstrates how to add authorization to an API using the Okta Spring Boot Starter. budicon: 500 topics: - quickstart @@ -30,24 +30,20 @@ This Quickstart uses Spring MVC. If you are using Spring WebFlux, the steps to s The sample project uses a `/src/main/resources/application.yml` file, which configures it to use the correct Auth0 **Domain** and **API Identifier** for your API. If you download the code from this page it will be automatically configured. If you clone the example from GitHub, you will need to fill it in yourself. ```yaml -auth0: - audience: ${apiIdentifier} -spring: - security: - oauth2: - resourceserver: - jwt: - issuer-uri: https://${account.namespace}/ +okta: + oauth2: + # Replace with the domain of your Auth0 tenant. + issuer: https://${account.namespace}/ + # Replace with the API Identifier for your Auth0 API. + audience: ${apiIdentifier} ``` | Attribute | Description| | --- | --- | -| `auth0.audience` | The unique identifier for your API. If you are following the steps in this tutorial it would be `https://quickstarts/api`. | -| `spring.security.oauth2.resourceserver.jwt.issuer-uri` | The issuer URI of the resource server, which will be the value of the `iss` claim in the JWT issued by Auth0. Spring Security will use this property to discover the authorization server's public keys and validate the JWT signature. The value will be your Auth0 domain with an `https://` prefix and a `/` suffix (the trailing slash is important). | +| `okta.oauth2.audience` | The unique identifier for your API. If you are following the steps in this tutorial it would be `https://quickstarts/api`. | +| `okta.oauth2.issuer` | The issuer URI of the resource server, which will be the value of the `iss` claim in the JWT issued by Auth0. Spring Security will use this property to discover the authorization server's public keys and validate the JWT signature. The value will be your Auth0 domain with an `https://` prefix and a `/` suffix (the trailing slash is important). | -## Validate Access Tokens - -### Install dependencies +## Install dependencies If you are using Gradle, you can add the required dependencies using the [Spring Boot Gradle Plugin](https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/) and the [Dependency Management Plugin](https://docs.spring.io/dependency-management-plugin/docs/current/reference/html/) to resolve dependency versions: @@ -55,13 +51,14 @@ If you are using Gradle, you can add the required dependencies using the [Spring // build.gradle plugins { - id 'org.springframework.boot' version '2.5.12' - id 'io.spring.dependency-management' version '1.0.9.RELEASE' + id 'java' + id 'org.springframework.boot' version '3.1.5' + id 'io.spring.dependency-management' version '1.1.3' } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' + implementation 'com.okta.spring:okta-spring-boot-starter:3.0.5' } ``` @@ -73,7 +70,7 @@ If you are using Maven, add the Spring dependencies to your `pom.xml` file: org.springframework.boot spring-boot-starter-parent - 2.5.12 + 3.1.5 @@ -83,113 +80,19 @@ If you are using Maven, add the Spring dependencies to your `pom.xml` file: spring-boot-starter-web - org.springframework.boot - spring-boot-starter-oauth2-resource-server + com.okta + okta-spring-boot-starter + 3.0.5 ``` -### Configure the resource server - -To configure the application as a Resource Server and validate the JWTs, create a class that will provide an instance of `SecurityFilterChain`, and add the `@EnableWebSecurity` annotation: - -```java -// src/main/java/com/auth0/example/security/SecurityConfig.java - -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.web.SecurityFilterChain; - -@EnableWebSecurity -public class SecurityConfig { - - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.oauth2Login(); - return http.build(); - } -} -``` - -### Validate the audience - -> Note: If you are using Spring Boot version 2.7 or higher, audience validation is supported out of the box by Spring Security. Instead of customizing beans as indicated below, you should just include the Auth0 API identifier as a value in the `spring.security.oauth2.resourceserver.jwt.audiences` array. -> Example: `spring.security.oauth2.resourceserver.jwt.audiences=http://api-identifier` - -In addition to validating the JWT, you also need to validate that the JWT is intended for your API by checking the `aud` claim of the JWT. Create a new class named `AudienceValidator` that implements the `OAuth2TokenValidator` interface: - -```java -// src/main/java/com/auth0/example/security/AudienceValidator.java - -import org.springframework.security.oauth2.core.OAuth2Error; -import org.springframework.security.oauth2.core.OAuth2TokenValidator; -import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; -import org.springframework.security.oauth2.jwt.Jwt; - -class AudienceValidator implements OAuth2TokenValidator { - private final String audience; - - AudienceValidator(String audience) { - this.audience = audience; - } - - public OAuth2TokenValidatorResult validate(Jwt jwt) { - OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null); - - if (jwt.getAudience().contains(audience)) { - return OAuth2TokenValidatorResult.success(); - } - return OAuth2TokenValidatorResult.failure(error); - } -} -``` - -Update the `SecurityConfig` class to configure a `JwtDecoder` bean that uses the `AudienceValidator`: - -```java -// src/main/java/com/auth0/example/security/SecurityConfig.java - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; -import org.springframework.security.oauth2.core.OAuth2TokenValidator; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.security.oauth2.jwt.JwtDecoder; -import org.springframework.security.oauth2.jwt.JwtDecoders; -import org.springframework.security.oauth2.jwt.JwtValidators; -import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; - -@EnableWebSecurity -public class SecurityConfig { - - @Value("<%= "${auth0.audience}" %>") - private String audience; - - @Value("<%= "${spring.security.oauth2.resourceserver.jwt.issuer-uri}" %>") - private String issuer; - - @Bean - JwtDecoder jwtDecoder() { - NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) - JwtDecoders.fromOidcIssuerLocation(issuer); - - OAuth2TokenValidator audienceValidator = new AudienceValidator(audience); - OAuth2TokenValidator withIssuer = JwtValidators.createDefaultWithIssuer(issuer); - OAuth2TokenValidator withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator); - - jwtDecoder.setJwtValidator(withAudience); - - return jwtDecoder; - } -} -``` - -## Protect API Endpoints +## Protect API endpoints <%= include('../_includes/_api_endpoints') %> +To configure the application as a Resource Server and validate the JWTs, create a class that will register a [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), an instance of `SecurityFilterChain`, and add the `@Configuration` annotation. + The example below shows how to secure API methods using the `HttpSecurity` object provided in the `filterChain()` method of the `SecurityConfig` class. Route matchers are used to restrict access based on the level of authorization required: ```java @@ -218,28 +121,16 @@ public class SecurityConfig { ::: note By default, Spring Security will create a `GrantedAuthority` for each scope in the `scope` claim of the JWT. This is what enables using the `hasAuthority("SCOPE_read:messages")` method to restrict access to a valid JWT that contains the `read:messages` scope. - -If your use case requires different claims to make authorization decisions, see the [Spring Security Reference Documentation](https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2resourceserver-authorization-extraction) to learn how to customize the extracted authorities. ::: ### Create the API controller -Create a new class named `Message`, which is the domain object the API will return: +Create a new record named `Message`, which will be the domain object the API will return: ```java // src/main/java/com/auth0/example/model/Message.java -public class Message { - private final String message; - - public Message(String message) { - this.message = message; - } - - public String getMessage() { - return this.message; - } -} +public record Message(String message) {} ``` Create a new class named `APIController` to handle requests to the endpoints: @@ -254,6 +145,10 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +/** + * Handles requests to "/api" endpoints. + * @see com.auth0.example.security.SecurityConfig to see how these endpoints are protected. + */ @RestController @RequestMapping(path = "api", produces = MediaType.APPLICATION_JSON_VALUE) // For simplicity of this sample, allow all origins. Real applications should configure CORS for their use case. diff --git a/articles/quickstart/backend/java-spring-security5/files/application.md b/articles/quickstart/backend/java-spring-security5/files/application.md index 8b101d0381..f12a521ce0 100644 --- a/articles/quickstart/backend/java-spring-security5/files/application.md +++ b/articles/quickstart/backend/java-spring-security5/files/application.md @@ -3,12 +3,10 @@ name: application.yml language: yaml --- ```yaml -auth0: - audience: ${apiIdentifier} -spring: - security: - oauth2: - resourceserver: - jwt: - issuer-uri: https://${account.namespace}/ +okta: + oauth2: + # Replace with the domain of your Auth0 tenant. + issuer: https://${account.namespace}/ + # Replace with the API Identifier for your Auth0 API. + audience: ${apiIdentifier} ``` \ No newline at end of file diff --git a/articles/quickstart/backend/java-spring-security5/files/audience-validator.md b/articles/quickstart/backend/java-spring-security5/files/audience-validator.md deleted file mode 100644 index 4dee42194d..0000000000 --- a/articles/quickstart/backend/java-spring-security5/files/audience-validator.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: AudienceValidator.java -language: java ---- -```java -import org.springframework.security.oauth2.core.OAuth2Error; -import org.springframework.security.oauth2.core.OAuth2TokenValidator; -import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; -import org.springframework.security.oauth2.jwt.Jwt; - -class AudienceValidator implements OAuth2TokenValidator { - private final String audience; - - AudienceValidator(String audience) { - this.audience = audience; - } - - public OAuth2TokenValidatorResult validate(Jwt jwt) { - OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null); - - if (jwt.getAudience().contains(audience)) { - return OAuth2TokenValidatorResult.success(); - } - return OAuth2TokenValidatorResult.failure(error); - } -} -``` \ No newline at end of file diff --git a/articles/quickstart/backend/java-spring-security5/files/message.md b/articles/quickstart/backend/java-spring-security5/files/message.md index 2b5a51290a..99f4056914 100644 --- a/articles/quickstart/backend/java-spring-security5/files/message.md +++ b/articles/quickstart/backend/java-spring-security5/files/message.md @@ -3,15 +3,9 @@ name: Message.java language: java --- ```java -public class Message { - private final String message; +/** + * Simple domain object for our API to return a message. + */ +public record Message(String message) {} - public Message(String message) { - this.message = message; - } - - public String getMessage() { - return this.message; - } -} ``` \ No newline at end of file diff --git a/articles/quickstart/backend/java-spring-security5/files/security-config.md b/articles/quickstart/backend/java-spring-security5/files/security-config.md index fe9d549af1..257bdbaa32 100644 --- a/articles/quickstart/backend/java-spring-security5/files/security-config.md +++ b/articles/quickstart/backend/java-spring-security5/files/security-config.md @@ -3,59 +3,40 @@ name: SecurityConfig.java language: java --- ```java -import org.springframework.beans.factory.annotation.Value; +package com.auth0.example.security; + + import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; -import org.springframework.security.oauth2.core.OAuth2TokenValidator; -import org.springframework.security.oauth2.jwt.*; import org.springframework.security.web.SecurityFilterChain; +import static org.springframework.security.config.Customizer.withDefaults; + /** * Configures our application with Spring Security to restrict access to our API endpoints. */ -@EnableWebSecurity +@Configuration public class SecurityConfig { - @Value("<%= "${auth0.audience}" %>") - private String audience; - - @Value("<%= "${spring.security.oauth2.resourceserver.jwt.issuer-uri}" %>") - private String issuer; - @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { /* This is where we configure the security required for our endpoints and setup our app to serve as an OAuth2 Resource Server, using JWT validation. */ - http.authorizeRequests() - .mvcMatchers("/api/public").permitAll() - .mvcMatchers("/api/private").authenticated() - .mvcMatchers("/api/private-scoped").hasAuthority("SCOPE_read:messages") - .and().cors() - .and().oauth2ResourceServer().jwt(); - return http.build(); - } - - @Bean - JwtDecoder jwtDecoder() { - /* - By default, Spring Security does not validate the "aud" claim of the token, to ensure that this token is - indeed intended for our app. Adding our own validator is easy to do: - */ - - NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) - JwtDecoders.fromOidcIssuerLocation(issuer); - - OAuth2TokenValidator audienceValidator = new AudienceValidator(audience); - OAuth2TokenValidator withIssuer = JwtValidators.createDefaultWithIssuer(issuer); - OAuth2TokenValidator withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator); - - jwtDecoder.setJwtValidator(withAudience); - - return jwtDecoder; + return http + .authorizeHttpRequests((authorize) -> authorize + .requestMatchers("/api/public").permitAll() + .requestMatchers("/api/private").authenticated() + .requestMatchers("/api/private-scoped").hasAuthority("SCOPE_read:messages") + ) + .cors(withDefaults()) + .oauth2ResourceServer(oauth2 -> oauth2 + .jwt(withDefaults()) + ) + .build(); } } + ``` \ No newline at end of file diff --git a/articles/quickstart/backend/java-spring-security5/index.yml b/articles/quickstart/backend/java-spring-security5/index.yml index 1cac540d5e..9baab5db4c 100644 --- a/articles/quickstart/backend/java-spring-security5/index.yml +++ b/articles/quickstart/backend/java-spring-security5/index.yml @@ -8,8 +8,8 @@ author: email: jim.anderson@auth0.com community: false sdk: - name: auth0-spring-security-api - url: https://github.com/auth0/auth0-spring-security-api + name: Okta Spring Boot Starter + url: https://github.com/okta/okta-spring-boot/ logo: spring alias: - spring security @@ -34,7 +34,7 @@ github: org: auth0-samples repo: auth0-spring-security5-api-sample requirements: - - Java 8 or above + - Java 17 next_steps: - path: 01-authorization list: diff --git a/articles/quickstart/backend/java-spring-security5/interactive.md b/articles/quickstart/backend/java-spring-security5/interactive.md index 4d09273327..bae669d759 100644 --- a/articles/quickstart/backend/java-spring-security5/interactive.md +++ b/articles/quickstart/backend/java-spring-security5/interactive.md @@ -11,7 +11,6 @@ topics: - spring files: - files/application - - files/audience-validator - files/security-config - files/message - files/api-controller @@ -40,8 +39,8 @@ The sample project uses a `/src/main/resources/application.yml` file, which conf | Attribute | Description| | --- | --- | -| `auth0.audience` | The unique identifier for your API. If you are following the steps in this tutorial it would be `https://quickstarts/api`. | -| `spring.security.oauth2.resourceserver.jwt.issuer-uri` | The value of the `iss` claim and the issuer URI of the resource server in the JWT issued by Auth0. Spring Security uses this property to discover the authorization server's public keys and validate the JWT signature. The value is Auth0 domain with an `https://` prefix and a `/` suffix (the trailing slash is important). | +| `okta.oauth2.audience` | The unique identifier for your API. If you are following the steps in this tutorial it would be `https://quickstarts/api`. | +| `okta.oauth2.issuer` | The issuer URI of the resource server, which will be the value of the `iss` claim in the JWT issued by Auth0. Spring Security will use this property to discover the authorization server's public keys and validate the JWT signature. The value will be your Auth0 domain with an `https://` prefix and a `/` suffix (the trailing slash is important). ## Install dependencies {{{ data-action=code data-code="application.yml#1:8" }}} @@ -51,13 +50,14 @@ If you are using Gradle, you can add the required dependencies using the [Spring // build.gradle plugins { - id 'org.springframework.boot' version '2.5.12' - id 'io.spring.dependency-management' version '1.0.9.RELEASE' + id 'java' + id 'org.springframework.boot' version '3.1.5' + id 'io.spring.dependency-management' version '1.1.3' } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' + implementation 'com.okta.spring:okta-spring-boot-starter:3.0.5' } ``` @@ -69,7 +69,7 @@ If you are using Maven, add the Spring dependencies to your `pom.xml` file: org.springframework.boot spring-boot-starter-parent - 2.5.12 + 3.1.5 @@ -79,39 +79,31 @@ If you are using Maven, add the Spring dependencies to your `pom.xml` file: spring-boot-starter-web - org.springframework.boot - spring-boot-starter-oauth2-resource-server + com.okta + okta-spring-boot-starter + 3.0.5 ``` -## Validate the audience {{{ data-action=code data-code="AudienceValidator.java#13:20" }}} - -To validate the JWT, you also need to validate that the JWT is intended for your API by checking the `aud` claim of the JWT. Create a new class named `AudienceValidator` that implements the `OAuth2TokenValidator` interface and override the `validate` method to verify whether the required `audience` is present. ## Configure the resource server {{{ data-action=code data-code="SecurityConfig.java" }}} -To configure the application as a Resource Server and validate the JWTs, create a class that will provide an instance of `SecurityFilterChain`, and add the `@EnableWebSecurity` annotation: +To configure the application as a Resource Server and validate the JWTs, create a class that will provide an instance of `SecurityFilterChain`, and add the `@Configuration` annotation. ### Protect API endpoints <%= include('../_includes/_api_endpoints') %> -The example below shows how to secure API methods using the `HttpSecurity` object provided in the `filterChain()` method of the `SecurityConfig` class. Route matchers restrict access based on the level of authorization required: +The example below shows how to secure API methods using the `HttpSecurity` object provided in the `filterChain()` method of the `SecurityConfig` class. Route matchers restrict access based on the level of authorization required. ::: note By default, Spring Security creates a `GrantedAuthority` for each scope in the `scope` claim of the JWT. This scope enables using the `hasAuthority("SCOPE_read:messages")` method to restrict access to a valid JWT that contains the `read:messages` scope. - -If your use case requires different claims to make authorization decisions, see the [Spring Security Reference Documentation](https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2resourceserver-authorization-extraction) to learn how to customize the extracted authorities. ::: -### Configure JWT Validator - -Update the `SecurityConfig` class to configure a `JwtDecoder` bean that uses the `AudienceValidator`. The `auth0.audience` value from `application.yml` validates the `aud` claim. The `issuer-uri` value from `application.yml` verifies the `issuer`. - ## Create the Domain Object {{{ data-action=code data-code="Message.java#1:11" }}} -To make your endpoint return a JSON, you can use a [POJO](https://en.wikipedia.org/wiki/Plain_old_Java_object) (Plain Old Java Object). The member variables of this object is serialized into the key value for your JSON. Create a new class named `Message` as an example domain object to return during the API calls. +To make your endpoint return a JSON, you can use a Java record. The member variables of this object is serialized into the key value for your JSON. Create a new record named `Message` as an example domain object to return during the API calls. ## Create the API controller {{{ data-action=code data-code="APIController.java" }}} diff --git a/articles/quickstart/native/flutter/interactive.md b/articles/quickstart/native/flutter/interactive.md index 7f963a9789..3d80b2580b 100644 --- a/articles/quickstart/native/flutter/interactive.md +++ b/articles/quickstart/native/flutter/interactive.md @@ -29,8 +29,6 @@ Auth0 allows you to quickly add authentication and access user profile informati The Flutter SDK currently only supports Flutter applications running on Android or iOS platforms. ::: -## Getting started - This quickstart assumes you already have a [Flutter](https://flutter.dev/) application up and running. If not, check out the [Flutter "getting started" guides](https://docs.flutter.dev/get-started/install) to get started with a simple app. You should also be familiar with the [Flutter command line tool](https://docs.flutter.dev/reference/flutter-cli). diff --git a/articles/quickstart/native/net-android-ios/01-login.md b/articles/quickstart/native/net-android-ios/01-login.md new file mode 100755 index 0000000000..992d4e2d37 --- /dev/null +++ b/articles/quickstart/native/net-android-ios/01-login.md @@ -0,0 +1,227 @@ +--- +title: Add login to your .NET Android or iOS application +default: true +description: This tutorial demonstrates how to add user login with Auth0 to a .NET Android or iOS application. +budicon: 448 +topics: + - quickstarts + - native + - xamarin + - dotnet + - android + - ios +github: + path: Quickstart/01-Login +contentType: tutorial +useCase: quickstart +--- + +::: note +This quickstart focusses on .NET Android and iOS, as they are the next generation of `Xamarin.Android` and `Xamarin.iOS`. If you are still using `Xamarin.Android` and `Xamarin.iOS`, you can follow this guide as well as integration is identical and the SDKs are compatible. +::: + + + +<%= include('../_includes/_getting_started', { library: 'Xamarin') %> + +<%= include('../../../_includes/_callback_url') %> + +Callback URLs are the URLs that Auth0 invokes after the authentication process. Auth0 routes your application back to this URL and appends additional parameters to it, including an access code which will be exchanged for an ID Token, Access Token, and Refresh Token. + +Since callback URLs can be manipulated, you will need to add your application's URL to your application's *Allowed Callback URLs* for security. This will enable Auth0 to recognize these URLs as valid. If omitted, authentication will not be successful. + +* For Android, the callback URL will be in the format + + ```text + YOUR_ANDROID_PACKAGE_NAME://${account.namespace}/android/YOUR_ANDROID_PACKAGE_NAME/callback + ``` + + where `YOUR_ANDROID_PACKAGE_NAME` is the Package Name for your application, such as `com.mycompany.myapplication`. + +* For iOS, the callback URL will be in the format + + ```text + YOUR_BUNDLE_IDENTIFIER://${account.namespace}/ios/YOUR_BUNDLE_IDENTIFIER/callback + ``` + + where `YOUR_BUNDLE_IDENTIFIER` is the Bundle Identifier for your application, such as `com.mycompany.myapplication`. + +Ensure that the Callback URL is in lowercase. + +<%= include('../../../_includes/_logout_url') %> + +::: note +If you are following along with the sample project you downloaded from the top of this page, the logout URL you need to add to the Allowed Logout URLs field is the same as the callback URL. +::: + +## Install Dependencies + +${snippet(meta.snippets.dependencies)} + +## Trigger Authentication + +To integrate Auth0 login into your application, instantiate an instance of the `Auth0Client` class, configuring the Auth0 Domain and Client ID: + +${snippet(meta.snippets.setup)} + +Then, call the `LoginAsync` method which will redirect the user to the login screen. You will typically do this in the event handler for a UI control such as a Login button. + +```cs +var loginResult = await client.LoginAsync(); +``` + +### Handing the callback URL + +After a user has logged in, they will be redirected back to your application at the **Callback URL** that was registered before. In both Android and iOS you need to handle this callback to complete the authentication flow. + +### Android + +Register an intent which will handle this callback URL. An easy way to do this is to register the intent on the same activity from which you called the `LoginAsync` method to initiate the authentication flow. + +```csharp +[Activity(Label = "AndroidSample", MainLauncher = true, Icon = "@drawable/icon", + LaunchMode = LaunchMode.SingleTask)] +[IntentFilter( + new[] { Intent.ActionView }, + Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, + DataScheme = "YOUR_ANDROID_PACKAGE_NAME", + DataHost = "${account.namespace}", + DataPathPrefix = "/android/YOUR_ANDROID_PACKAGE_NAME/callback")] +public class MainActivity : Activity +{ + // Code omitted +} +``` + +Replace `YOUR_ANDROID_PACKAGE_NAME` in the code sample above with the actual Package Name for your application, such as `com.mycompany.myapplication`. Also ensure that all the text for the `DataScheme`, `DataHost`, and `DataPathPrefix` is in lower case. Also, set `LaunchMode = LaunchMode.SingleTask` for the `Activity`, otherwise the system will create a new instance of the activity every time the Callback URL gets called. + +Now write code to handle the intent. You can do this by overriding the `OnNewIntent` method. Inside the method you need to call the `Send` method on the `ActivityMediator` to complete the authentication cycle: + +```csharp +protected override async void OnNewIntent(Intent intent) +{ + base.OnNewIntent(intent); + + Auth0.OidcClient.ActivityMediator.Instance.Send(intent.DataString); +} +``` + +### iOS + +Register the URL scheme for your Callback URL which your application should handle: + +1. Open your application's `Info.plist` file in Visual Studio for Mac, and go to the **Advanced** tab. +2. Under **URL Types**, click the **Add URL Type** button +3. Set the **Identifier** as `Auth0`, the **URL Schemes** the same as your application's **Bundle Identifier**, and the **Role** as `None` + +This is an example of the XML representation of your `info.plist` file after you have added the URL Type: + +```xml +CFBundleURLTypes + + + CFBundleTypeRole + None + CFBundleURLName + Auth0 + CFBundleURLSchemes + + YOUR_BUNDLE_IDENTIFIER + + + +``` + +You need to handle the Callback URL in the `OpenUrl` event in your `AppDelegate` class. You need to notify the Auth0 OIDC Client to finish the authentication flow by calling the `Send` method of the `ActivityMediator` singleton, pass along the URL that was sent in: + +```csharp +using Auth0.OidcClient; + +[Register("AppDelegate")] +public class AppDelegate : UIApplicationDelegate +{ + public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) + { + ActivityMediator.Instance.Send(url.AbsoluteString); + + return true; + } +} +``` + +### Run the application + +With the above code in place, a user can log in to your application using Auth0. + +
+ Universal Login +
+ +## Accessing the User's Information + +The returned login result will indicate whether authentication was successful and if so contain the tokens and claims of the user. + +### Authentication Error + +You can check the `IsError` property of the result to see whether the login has failed. The `ErrorMessage` will contain more information regarding the error which occurred. + +```csharp +var loginResult = await client.LoginAsync(); + +if (loginResult.IsError) +{ + Debug.WriteLine($"An error occurred during login: {loginResult.Error}") +} +``` + +### Accessing the tokens + +On successful login, the login result will contain the ID Token and Access Token in the `IdentityToken` and `AccessToken` properties respectively. + +```csharp +var loginResult = await client.LoginAsync(); + +if (!loginResult.IsError) +{ + Debug.WriteLine($"id_token: {loginResult.IdentityToken}"); + Debug.WriteLine($"access_token: {loginResult.AccessToken}"); +} +``` + +### Obtaining the User Information + +On successful login, the login result will contain the user information in the `User` property, which is a [ClaimsPrincipal](https://msdn.microsoft.com/en-us/library/system.security.claims.claimsprincipal(v=vs.110).aspx). + +To obtain information about the user, you can query the claims. You can, for example, obtain the user's name and email address from the `name` and `email` claims: + +```csharp +if (!loginResult.IsError) +{ + Debug.WriteLine($"name: {loginResult.User.FindFirst(c => c.Type == "name")?.Value}"); + Debug.WriteLine($"email: {loginResult.User.FindFirst(c => c.Type == "email")?.Value}"); +} +``` + +::: note +The exact claims returned will depend on the scopes that were requested. For more information see the [Using Scopes](https://auth0.github.io/auth0-oidc-client-net/documentation/advanced-scenarios/scopes.html) in the Auth0 OIDC Application documentation. +::: + +You can obtain a list of all the claims contained in the ID Token by iterating through the `Claims` collection: + +```csharp +if (!loginResult.IsError) +{ + foreach (var claim in loginResult.User.Claims) + { + Debug.WriteLine($"{claim.Type} = {claim.Value}"); + } +} +``` + +## Logout + +To log the user out call the `LogoutAsync` method. + +```csharp +BrowserResultType browserResult = await client.LogoutAsync(); +``` diff --git a/articles/quickstart/native/net-android-ios/_configure_urls_interactive.md b/articles/quickstart/native/net-android-ios/_configure_urls_interactive.md new file mode 100644 index 0000000000..471c0f77bb --- /dev/null +++ b/articles/quickstart/native/net-android-ios/_configure_urls_interactive.md @@ -0,0 +1,37 @@ +## Configure Auth0 {{{ data-action=configure }}} + +To use Auth0 services, you need to have an application set up in the Auth0 Dashboard. The Auth0 application is where you will configure how you want authentication to work for your project. + +### Configure an application + +Use the interactive selector to create a new "Native Application", or select an existing application that represents the project you want to integrate with. Every application in Auth0 is assigned an alphanumeric, unique client ID that your application code will use to call Auth0 APIs through the SDK. + +Any settings you configure using this quickstart will automatically update for your application in the Dashboard, which is where you can manage your applications in the future. + +If you would rather explore a complete configuration, you can view a sample application instead. + +### Configure Callback URLs + +A callback URL is a URL in your application that you would like Auth0 to redirect users to after they have authenticated. If not set, users will not be returned to your application after they log in. + +::: note +If you are following along with our sample project, set this to one of the following URLs, depending on your platform: + +**Android**: `YOUR_PACKAGE_NAME://${account.namespace}/android/YOUR_PACKAGE_NAME/callback` + +**iOS**: `YOUR_BUNDLE_ID://${account.namespace}/ios/YOUR_BUNDLE_ID/callback` +::: + +### Configure Logout URLs + +A logout URL is a URL in your application that you would like Auth0 to redirect users to after they have logged out. If not set, users will not be able to log out from your application and will receive an error. + +::: note +If you are following along with our sample project, set this to one of the following URLs, depending on your platform: + +**Android**: `YOUR_PACKAGE_NAME://${account.namespace}/android/YOUR_PACKAGE_NAME/callback` + +**iOS**: `YOUR_BUNDLE_ID://${account.namespace}/ios/YOUR_BUNDLE_ID/callback` +::: + +Lastly, be sure that the **Application Type** for your application is set to **Native** in the [Application Settings](${manage_url}/#/applications/${account.clientId}/settings). diff --git a/articles/quickstart/native/net-android-ios/download.md b/articles/quickstart/native/net-android-ios/download.md new file mode 100644 index 0000000000..6aca335de9 --- /dev/null +++ b/articles/quickstart/native/net-android-ios/download.md @@ -0,0 +1,22 @@ +To run the sample first set the **Allowed Callback URLs** in the [Application Settings](${manage_url}/#/applications/${account.clientId}/settings) so it works for both Android and iOS apps: + + ```text +com.auth0.quickstart://${account.namespace}/android/com.auth0.quickstart/callback com.auth0.iossample://${account.namespace}/ios/com.auth0.iossample/callback + ``` + +Set the **Allowed Logout URLs** in the [Application Settings](${manage_url}/#/applications/${account.clientId}/settings) so it works for both Android and iOS apps: + + ```text +com.auth0.quickstart://${account.namespace}/android/com.auth0.quickstart/callback com.auth0.iossample://${account.namespace}/ios/com.auth0.iossample/callback + ``` + +Then, to run it **on Windows**: + +1) Open the AndroidSample.sln or iOSSample.sln solution in [Visual Studio 2017](https://www.visualstudio.com/vs/). +2) Click the **Start** button (the green play button), optionally selecting your target device. +You can also start the application using the **Debug | Start Debugging** option from the main menu. + +To run it on **macOS**: + +1) Open the AndroidSample.sln or iOSSample.sln solution in [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). +2) Click the **Start** button (the play button), optionally selecting your target device. You can also start the application using the **Run | Start Debugging** option from the application menu diff --git a/articles/quickstart/native/net-android-ios/files/app-delegate.md b/articles/quickstart/native/net-android-ios/files/app-delegate.md new file mode 100644 index 0000000000..4968ce3e1e --- /dev/null +++ b/articles/quickstart/native/net-android-ios/files/app-delegate.md @@ -0,0 +1,19 @@ +--- +name: AppDelegate.cs +language: csharp +--- + +```csharp +using Auth0.OidcClient; + +[Register("AppDelegate")] +public class AppDelegate : UIApplicationDelegate +{ + public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) + { + ActivityMediator.Instance.Send(url.AbsoluteString); + + return true; + } +} +``` \ No newline at end of file diff --git a/articles/quickstart/native/net-android-ios/files/main-activity.md b/articles/quickstart/native/net-android-ios/files/main-activity.md new file mode 100644 index 0000000000..513b7067ee --- /dev/null +++ b/articles/quickstart/native/net-android-ios/files/main-activity.md @@ -0,0 +1,57 @@ +--- +name: MainActivity.cs +language: csharp +--- + +```csharp +// Example of a full Android Activity +[Activity(Label = "AndroidSample", MainLauncher = true, Icon = "@drawable/icon", + LaunchMode = LaunchMode.SingleTask)] +[IntentFilter( + new[] { Intent.ActionView }, + Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, + DataScheme = "YOUR_ANDROID_PACKAGE_NAME", + DataHost = "{yourDomain}", + DataPathPrefix = "/android/YOUR_ANDROID_PACKAGE_NAME/callback")] +public class MainActivity : Activity +{ + private Auth0Client _auth0Client; + + protected override void OnNewIntent(Intent intent) + { + base.OnNewIntent(intent); + ActivityMediator.Instance.Send(intent.DataString); + } + + protected override void OnCreate(Bundle bundle) + { + base.OnCreate(bundle); + + Auth0ClientOptions clientOptions = new Auth0ClientOptions + { + Domain = "${account.namespace}" + ClientId = "${account.clientId}" + }; + + _auth0Client = new Auth0Client(clientOptions, this); + } + + private async void LoginButtonOnClick(object sender, EventArgs eventArgs) + { + var loginResult = await _auth0Client.LoginAsync(); + + if (loginResult.IsError == false) + { + var user = loginResult.User; + var name = user.FindFirst(c => c.Type == "name")?.Value; + var email = user.FindFirst(c => c.Type == "email")?.Value; + var picture = user.FindFirst(c => c.Type == "picture")?.Value; + } + } + + private async void LogoutButtonOnClick(object sender, EventArgs e) + { + await _auth0Client.LogoutAsync(); + } +} +``` \ No newline at end of file diff --git a/articles/quickstart/native/net-android-ios/files/my-view-controller.md b/articles/quickstart/native/net-android-ios/files/my-view-controller.md new file mode 100644 index 0000000000..e67f6d00fc --- /dev/null +++ b/articles/quickstart/native/net-android-ios/files/my-view-controller.md @@ -0,0 +1,47 @@ +--- +name: MyViewController.cs +language: csharp +--- + +```csharp +// Example of a full iOS UIViewController +public partial class MyViewController : UIViewController +{ + private Auth0Client _auth0Client; + + public MyViewController() : base("MyViewController", null) + { + } + + public override void ViewDidLoad() + { + base.ViewDidLoad(); + + Auth0ClientOptions clientOptions = new Auth0ClientOptions + { + Domain = "${account.namespace}" + ClientId = "${account.clientId}" + }; + + _auth0Client = new Auth0Client(clientOptions, this); + } + + private async void LoginButton_TouchUpInside(object sender, EventArgs e) + { + var loginResult = await _auth0Client.LoginAsync(); + + if (loginResult.IsError == false) + { + var user = loginResult.User; + var name = user.FindFirst(c => c.Type == "name")?.Value; + var email = user.FindFirst(c => c.Type == "email")?.Value; + var picture = user.FindFirst(c => c.Type == "picture")?.Value; + } + } + + private async void LogoutButton_TouchUpInside(object sender, EventArgs e) + { + await _auth0Client.LogoutAsync(); + } +} +``` \ No newline at end of file diff --git a/articles/quickstart/native/net-android-ios/index.yml b/articles/quickstart/native/net-android-ios/index.yml new file mode 100755 index 0000000000..7c97755a57 --- /dev/null +++ b/articles/quickstart/native/net-android-ios/index.yml @@ -0,0 +1,53 @@ +title: .NET Android and iOS +# TODO remove 'image' once new QS page is live. Then only use 'logo'. +image: /media/platforms/xamarin.png +logo: dotnet +author: + name: Frederik Prijck + email: frederik.prijck@auth0.com + community: false +language: + - C# +framework: + - net-android-ios +hybrid: false +topics: + - quickstart +contentType: tutorial +useCase: quickstart +snippets: + dependencies: native-platforms/xamarin/dependencies + setup: native-platforms/xamarin/setup +seo_alias: xamarin +default_article: 01-login +hidden_articles: + - interactive +articles: + - 01-login +show_steps: true +github: + org: auth0-samples + repo: auth0-xamarin-oidc-samples +sdk: + name: auth0-oidc-client-net + url: https://github.com/auth0/auth0-oidc-client-net + logo: xamarin +requirements: + - Visual Studio 2022+ or Visual Studio for Mac + - Xamarin for Visual Studio + - .NET6+ +next_steps: + - path: 01-login + list: + - text: Configure other identity providers + icon: 345 + href: "/identityproviders" + - text: Enable multifactor authentication + icon: 345 + href: "/multifactor-authentication" + - text: Learn about attack protection + icon: 345 + href: "/attack-protection" + - text: Learn about rules + icon: 345 + href: "/rules" diff --git a/articles/quickstart/native/net-android-ios/interactive.md b/articles/quickstart/native/net-android-ios/interactive.md new file mode 100644 index 0000000000..c9e2545796 --- /dev/null +++ b/articles/quickstart/native/net-android-ios/interactive.md @@ -0,0 +1,208 @@ +--- +title: Add login to your .NET Android or iOS application +default: true +description: This tutorial demonstrates how to add user login with Auth0 to a .NET Android or iOS application. +budicon: 448 +topics: + - quickstarts + - native + - xamarin + - dotnet + - android + - ios +github: + path: Quickstart/01-Login +contentType: tutorial +useCase: quickstart +interactive: true +files: + - files/main-activity + - files/app-delegate + - files/my-view-controller +--- + +# Add Login to .NET Android and iOS App + +Auth0 allows you to add authentication to almost any application type quickly. This guide demonstrates how to integrate Auth0, add authentication, and display user profile information in any .NET Android and iOS application using the Auth0 SDKs for [Android](https://www.nuget.org/packages/Auth0.OidcClient.AndroidX/) and [iOS](https://www.nuget.org/packages/Auth0.OidcClient.iOS). + +::: note +This quickstart focusses on .NET Android and iOS, as they are the next generation of `Xamarin.Android` and `Xamarin.iOS`. If you are still using `Xamarin.Android` and `Xamarin.iOS`, you can follow this guide as well as integration is identical and the SDKs are compatible. +::: + +To use this quickstart, you’ll need to: + +- Sign up for a free Auth0 account or log in to Auth0. +- Have a working Android or iOS project using .NET 6 (or above) that you want to integrate with. Alternatively, you can view or download a sample application after logging in. + +<%= include('_configure_urls_interactive') %> + +## Install the Auth0 SDK + +Auth0 provides an [Android](https://www.nuget.org/packages/Auth0.OidcClient.AndroidX/) and [iOS](https://www.nuget.org/packages/Auth0.OidcClient.iOS) SDK to simplify the process of implementing Auth0 authentication in .NET Android and iOS applications. + +Use the NuGet Package Manager (Tools -> Library Package Manager -> Package Manager Console) to install the `Auth0.OidcClient.AndroidX` or `Auth0.OidcClient.iOS` package, depending on whether you are building an Android or iOS application. + +Alternatively, you can use the Nuget Package Manager Console (`Install-Package`) or the `dotnet` CLI (`dotnet add`). + +```ps +Install-Package Auth0.OidcClient.AndroidX +Install-Package Auth0.OidcClient.iOS +``` +``` +dotnet add Auth0.OidcClient.AndroidX +dotnet add Auth0.OidcClient.iOS +``` + +## Instantiate the Auth0Client + +To integrate Auth0 into your application, instantiate an instance of the `Auth0Client` class, passing an instance of `Auth0ClientOptions` that contains your Auth0 Domain and Client ID. + +```csharp +using Auth0.OidcClient; + +var client = new Auth0Client(new Auth0ClientOptions +{ + Domain = "${account.namespace}", + ClientId = "${account.namespace}" +}, this); +``` + +By default, the SDK will leverage Chrome Custom Tabs for Android and ASWebAuthenticationSession for iOS. + +::::checkpoint + +:::checkpoint-default + +Your `Auth0Client` should now be properly instantiated. Run your application to verify that: +- the `Auth0Client` is instantiated correctly in the `Activity` (Android) or `UIViewController` (iOS) +- your application is not throwing any errors related to Auth0 + +::: + +:::checkpoint-failure +Sorry about that. Here are a couple things to double-check: +* make sure the correct application is selected +* did you save after entering your URLs? +* make sure the domain and client ID are imported correctly + +Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. + +::: +:::: + +## Configure Android {{{ data-action="code" data-code="MainActivity.cs#2-9,14-18" }}} + +After a user successfully authenticates, they will be redirected to the callback URL you set up earlier in this quickstart. + +To handle the callback on Android devices, you need to register an intent that handles this callback URL. An easy way to do this is to register the intent on the same activity from which you called the LoginAsync method to instantiate the authentication flow. + +Ensure to replace `YOUR_ANDROID_PACKAGE_NAME` in the code sample with the actual Package Name for your application, such as com.mycompany.myapplication, and ensure that all the text for the `DataScheme`, `DataHost`, and `DataPathPrefix` is in lower case. Also, set `LaunchMode = LaunchMode.SingleTask` for the Activity, otherwise the system will create a new instance of the activity every time the Callback URL gets called. + +Additionally, you need to handle the intent in the `OnNewIntent` event in your `Activity` class. You need to notify the Auth0 OIDC Client to finish the authentication flow by calling the `Send` method of the `ActivityMediator` singleton, passing along the URL that was sent in. + +## Configure iOS {{{ data-action="code" data-code="AppDelegate.cs#6-11" }}} + +After a user successfully authenticates, they will be redirected to the callback URL you set up earlier in this quickstart. + +To handle the callback on iOS devices: + +- Open your application's `Info.plist` file in Visual Studio, and go to the **Advanced** tab. +- Under **URL Types**, click the **Add URL Type** button +- Set the **Identifier** as Auth0, the **URL Schemes** the same as your application's Bundle Identifier, and the **Role** as None + +This is an example of the XML representation of your `info.plist` file after you have added the URL Type: + +```xml +CFBundleURLTypes + + + CFBundleTypeRole + None + CFBundleURLName + Auth0 + CFBundleURLSchemes + + YOUR_BUNDLE_IDENTIFIER + + + +``` + +Additionally, you need to handle the Callback URL in the `OpenUrl` event in your `AppDelegate` class. You need to notify the Auth0 OIDC Client to finish the authentication flow by calling the `Send` method of the `ActivityMediator` singleton, passing along the URL that was sent in. + +## Add Login to Your Application + +Now that you have configured your Auth0 Application and the Auth0 SDK, you need to set up login for your project. To do this, you will use the SDK’s `LoginAsync()` method to create a login button that redirects users to the Auth0 Universal Login page. + +```csharp +var loginResult = await client.LoginAsync(); +``` + +If there isn't any error, you can access the `User`, `IdentityToken`, `AccessToken` and `RefreshToken` on the `LoginResult` returned from `LoginAsync()`. + +::::checkpoint + +:::checkpoint-default + +You should now be able to log in or sign up using a username and password. + +Click the login button and verify that: +* your Android or iOS application redirects you to the Auth0 Universal Login page +* you can log in or sign up +* Auth0 redirects you to your application. + +::: + +:::checkpoint-failure +Sorry about that. Here's something to double-check: +* you called `LoginAsync` as expected + +Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. + +::: +:::: + +## Add Logout to Your Application + +Users who log in to your project will also need a way to log out. Create a logout button using the SDK’s `LogoutAsync()` method. When users log out, they will be redirected to your Auth0 logout endpoint, which will then immediately redirect them back to the logout URL you set up earlier in this quickstart. + +```csharp +await client.LogoutAsync(); +``` + +::::checkpoint + +:::checkpoint-default + +Run your application and click the logout button, verify that: +* your Android or iOS application redirects you to the address you specified as one of the Allowed Logout URLs in your Application Settings +* you are no longer logged in to your application + +::: + +:::checkpoint-failure +Sorry about that. Here are a couple things to double-check: +* you configured the correct Logout URL +* you called `LogoutAsync` as expected. + +Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. + +::: + +:::: + +## Show User Profile Information + +Now that your users can log in and log out, you will likely want to be able to retrieve the [profile information](https://auth0.com/docs/users/concepts/overview-user-profile) associated with authenticated users. For example, you may want to be able to display a logged-in user’s name or profile picture in your project. + +The Auth0 SDK for Android and iOS provides user information through the `LoginResult.User` property. + +```csharp +if (loginResult.IsError == false) +{ + var user = loginResult.User; + var name = user.FindFirst(c => c.Type == "name")?.Value; + var email = user.FindFirst(c => c.Type == "email")?.Value; + var picture = user.FindFirst(c => c.Type == "picture")?.Value; +} +``` \ No newline at end of file diff --git a/articles/quickstart/native/wpf-winforms/files/mainwindow.md b/articles/quickstart/native/wpf-winforms/files/mainwindow.md new file mode 100644 index 0000000000..b28d2e761a --- /dev/null +++ b/articles/quickstart/native/wpf-winforms/files/mainwindow.md @@ -0,0 +1,49 @@ +--- +name: MainWindow.xaml.cs +language: csharp +--- + +```csharp +using Auth0.OidcClient; + +public partial class MainWindow : Window +{ + private Auth0Client client; + + public MainWindow() + { + InitializeComponent(); + InitializeClient(); + } + + private InitializeClient() + { + Auth0ClientOptions clientOptions = new Auth0ClientOptions + { + Domain = "${account.namespace}" + ClientId = "${account.clientId}" + }; + client = new Auth0Client(clientOptions); + clientOptions.PostLogoutRedirectUri = clientOptions.RedirectUri; + } + + private async void LoginButton_OnClick(object sender, RoutedEventArgs e) + { + var loginResult = await client.LoginAsync(); + + if (loginResult.IsError == false) + { + var user = loginResult.User; + var name = user.FindFirst(c => c.Type == "name")?.Value; + var email = user.FindFirst(c => c.Type == "email")?.Value; + var picture = user.FindFirst(c => c.Type == "picture")?.Value; + } + } + + private async void LogoutButton_Click(object sender, RoutedEventArgs e) + { + await client.LogoutAsync(); + } +} +``` + diff --git a/articles/quickstart/native/wpf-winforms/index.yml b/articles/quickstart/native/wpf-winforms/index.yml index c8e56da7f2..f562d7baf8 100644 --- a/articles/quickstart/native/wpf-winforms/index.yml +++ b/articles/quickstart/native/wpf-winforms/index.yml @@ -1,7 +1,7 @@ title: WPF / Winforms # TODO remove 'image' once new QS page is live. Then only use 'logo'. image: /media/platforms/asp.png -logo: windows +logo: dotnet-platform author: name: Damien Guard email: damien.guard@auth0.com @@ -30,6 +30,8 @@ seo_alias: wpf-winforms default_article: 01-login articles: - 01-login +hidden_articles: + - "interactive" show_steps: true github: org: auth0-samples diff --git a/articles/quickstart/native/wpf-winforms/interactive.md b/articles/quickstart/native/wpf-winforms/interactive.md new file mode 100644 index 0000000000..83725ce193 --- /dev/null +++ b/articles/quickstart/native/wpf-winforms/interactive.md @@ -0,0 +1,155 @@ +--- +title: Add login to your WinForms and WPF application +default: true +description: This tutorial demonstrates how to add user login with Auth0 to a WPF and WinForms application. +budicon: 448 +topics: + - quickstarts + - native + - windows + - wpf + - winforms +github: + path: Quickstart/00-Starter-Seed +contentType: tutorial +useCase: quickstart +interactive: true +files: + - files/mainwindow +--- + +# Add Login to Your WPF or WinForms App + +Auth0 allows you to add authentication to almost any application type quickly. This guide demonstrates how to integrate Auth0, add authentication, and display user profile information in any WPF and WinForms application using the Auth0 SDKs for [WPF](https://www.nuget.org/packages/Auth0.OidcClient.WPF/) and [WinForms](https://www.nuget.org/packages/Auth0.OidcClient.WinForms). + +To use this quickstart, you’ll need to: + +- Sign up for a free Auth0 account or log in to Auth0. +- Have a working WPF or WinForms project that you want to integrate with. Alternatively, you can view or download a sample application after logging in. + +<%= include('../../_includes/_configure_auth0_interactive', { + callback: 'http://' + account.namespace + ':4200/mobile', + returnTo: 'http://' + account.namespace + ':4200/mobile' +}) %> + +## Install the Auth0 SDK + +Auth0 provides a [WPF](https://www.nuget.org/packages/Auth0.OidcClient.WPF/) and [WinForms](https://www.nuget.org/packages/Auth0.OidcClient.WinForms) SDK to simplify the process of implementing Auth0 authentication in WPF and WinForms applications. + +Use the NuGet Package Manager (Tools -> Library Package Manager -> Package Manager Console) to install the `Auth0.OidcClient.WPF` or `Auth0.OidcClient.WinForms` package, depending on whether you are building a WPF or Windows Forms application. + +Alternatively, you can use the Nuget Package Manager Console (`Install-Package`) or the `dotnet` CLI (`dotnet add`). + +```ps +Install-Package Auth0.OidcClient.WPF +Install-Package Auth0.OidcClient.WinForms +``` +``` +dotnet add Auth0.OidcClient.WPF +dotnet add Auth0.OidcClient.WinForms +``` + +## Instantiate the Auth0Client {{{ data-action="code" data-code="MainWindow.xaml.cs#13:22" }}} + +To integrate Auth0 into your application, instantiate an instance of the Auth0Client class, passing an instance of Auth0ClientOptions that contains your Auth0 Domain and Client ID. + +By default, the SDK will leverage [WebView2](https://learn.microsoft.com/en-us/microsoft-edge/webview2/) for .NET6 and above, while relying on the older WebView on applications using any version that predates .NET6. + +::::checkpoint + +:::checkpoint-default + +Your `Auth0Client` should now be properly instantiated. Run your application to verify that: +- the `Auth0Client` is instantiated correctly +- your application is not throwing any errors related to Auth0 + +::: + +:::checkpoint-failure +Sorry about that. Here are a couple things to double-check: +* make sure the correct application is selected +* did you save after entering your URLs? +* make sure the domain and client ID are imported correctly + +Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. + +::: +:::: + +## Add Login to Your Application {{{ data-action="code" data-code="MainWindow.xaml.cs#24:35" }}} + +Now that you have configured your Auth0 Application and the Auth0 SDK, you need to set up login for your project. To do this, you will use the SDK’s `LoginAsync()` method to create a login button that redirects users to the Auth0 Universal Login page. After a user successfully authenticates, they will be redirected to the callback URL you set up earlier in this quickstart. + +If there isn't any error, you can access the `User`, `IdentityToken`, `AccessToken` and `RefreshToken` on the `LoginResult` returned from `LoginAsync()`. + +::::checkpoint + +:::checkpoint-default + +You should now be able to log in or sign up using a username and password. + +Click the login button and verify that: +* your WPF or WinForms Application redirects you to the Auth0 Universal Login page +* you can log in or sign up +* Auth0 redirects you to your application. + +::: + +:::checkpoint-failure +Sorry about that. Here's something to double-check: +* you called `LoginAsync` as expected + +Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. + +::: +:::: + +## Add Logout to Your Application {{{ data-action="code" data-code="MainWindow.xaml.cs#37:40" }}} + +Users who log in to your project will also need a way to log out. Create a logout button using the SDK’s `LogoutAsync()` method. When users log out, they will be redirected to your Auth0 logout endpoint, which will then immediately redirect them back to the logout URL you set up earlier in this quickstart. + +::::checkpoint + +:::checkpoint-default + +Run your application and click the logout button, verify that: +* your WPF or WinForms application redirects you to the address you specified as one of the Allowed Logout URLs in your Application Settings +* you are no longer logged in to your application + +::: + +:::checkpoint-failure +Sorry about that. Here are a couple things to double-check: +* you configured the correct Logout URL +* you called `LogoutAsync` as expected. + +Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. + +::: + +:::: + +## Show User Profile Information {{{ data-action=code data-code="MainWindow.xaml.js#30:33" }}} + +Now that your users can log in and log out, you will likely want to be able to retrieve the [profile information](https://auth0.com/docs/users/concepts/overview-user-profile) associated with authenticated users. For example, you may want to be able to display a logged-in user’s name or profile picture in your project. + +The Auth0 SDK for WPF and WinForms provides user information through the `LoginResult.User` property. + +::::checkpoint + +:::checkpoint-default + +Verify that: +* you can display the user's name or any other user property after you have logged in + +::: + +:::checkpoint-failure +Sorry about that. Here are a couple things to double-check: +* the `LoginResult.IsError` is false +* if the `LoginResult.IsError` isn't false, be sure to check `LoginResult.Error` for details. + +Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. +::: + +:::: \ No newline at end of file diff --git a/articles/quickstart/native/xamarin/index.yml b/articles/quickstart/native/xamarin/index.yml index 45085b87ee..689696d443 100755 --- a/articles/quickstart/native/xamarin/index.yml +++ b/articles/quickstart/native/xamarin/index.yml @@ -3,8 +3,8 @@ title: Xamarin image: /media/platforms/xamarin.png logo: xamarin author: - name: Damien Guard - email: damien.guard@auth0.com + name: Frederik Prijck + email: frederik.prijck@auth0.com community: false language: - C# diff --git a/articles/quickstart/native/xamarin/interactive.md b/articles/quickstart/native/xamarin/interactive.md index 5aa18d3fea..0222e08736 100644 --- a/articles/quickstart/native/xamarin/interactive.md +++ b/articles/quickstart/native/xamarin/interactive.md @@ -62,9 +62,9 @@ using Auth0.OidcClient; var client = new Auth0Client(new Auth0ClientOptions { - Domain = "{yourDomain}", - ClientId = "{yourClientId}" -}, this); + Domain = "${account.namespace}", + ClientId = "${account.namespace}" +}); ``` By default, the SDK will leverage Chrome Custom Tabs for Android and ASWebAuthenticationSession for iOS. diff --git a/articles/quickstart/spa/flutter/interactive.md b/articles/quickstart/spa/flutter/interactive.md index f2146dd20a..6b54ceb73d 100644 --- a/articles/quickstart/spa/flutter/interactive.md +++ b/articles/quickstart/spa/flutter/interactive.md @@ -30,8 +30,6 @@ Auth0 allows you to quickly add authentication and access user profile informati The Flutter SDK currently only supports Flutter applications running on Android, iOS, or Web platforms. ::: -## Getting started - This quickstart assumes you already have a [Flutter](https://flutter.dev/) application up and running. If not, check out the [Flutter "getting started" guides](https://docs.flutter.dev/get-started/install) to get started with a simple app. You should also be familiar with the [Flutter command line tool](https://docs.flutter.dev/reference/flutter-cli). diff --git a/articles/quickstart/webapp/aspnet-core/index.yml b/articles/quickstart/webapp/aspnet-core/index.yml index be26a8a0ea..da7460007e 100644 --- a/articles/quickstart/webapp/aspnet-core/index.yml +++ b/articles/quickstart/webapp/aspnet-core/index.yml @@ -1,7 +1,7 @@ title: ASP.NET Core MVC # TODO remove 'image' once new QS page is live. Then only use 'logo'. image: /media/platforms/asp.png -logo: dotnet +logo: dotnet-platform author: name: Frederik Prijck email: frederik.prijck@auth0.com diff --git a/articles/quickstart/webapp/java-spring-boot/01-login.md b/articles/quickstart/webapp/java-spring-boot/01-login.md index 1e1121d9bc..afbcf863a3 100644 --- a/articles/quickstart/webapp/java-spring-boot/01-login.md +++ b/articles/quickstart/webapp/java-spring-boot/01-login.md @@ -1,6 +1,6 @@ --- title: Login -description: Spring Boot and Spring Security support OIDC natively, enabling you to add authentication to your application without the need for any additional libraries. This guide demonstrates how to integrate Auth0 with any new or existing Spring Boot 2 web application. +description: The Okta Spring Boot Starter makes it easy to add login to your Spring Boot application. budicon: 448 topics: - quickstarts @@ -17,15 +17,15 @@ useCase: quickstart This tutorial uses [Spring MVC](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html). If you are using [Spring WebFlux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#spring-web-reactive), the steps to add authentication are similar, but some of the implementation details are different. Refer to the [Spring Boot WebFlux Sample Code](https://github.com/auth0-samples/auth0-spring-boot-login-samples/tree/master/webflux-login) to see how to integrate Auth0 with your Spring Boot WebFlux application. ::: -<%= include('../_includes/_getting_started', { library: 'Java Spring Security', callback: 'http://localhost:3000/login/oauth2/code/auth0' }) %> +<%= include('../_includes/_getting_started', { library: 'Java Spring Security', callback: 'http://localhost:3000/login/oauth2/code/okta' }) %> <%= include('../../../_includes/_logout_url', { returnTo: 'http://localhost:3000/' }) %> ## Configure Spring Boot Application -### Add Spring dependencies +### Add dependencies -Spring Boot provides a `spring-boot-starter-oauth2-client` starter, which provides all the Spring Security dependencies needed to add authentication to your web application. +To integrate your Spring Boot application with Auth0, include the [Okta Spring Boot Starter](https://github.com/okta/okta-spring-boot/) in your application's dependencies. :::note This guide uses [Thymeleaf](https://www.thymeleaf.org/) and the [Spring Security integration module](https://github.com/thymeleaf/thymeleaf-extras-springsecurity) for the view layer. If you are using a different view technology, the Spring Security configuration and components remain the same. @@ -36,14 +36,15 @@ If you're using Gradle, you can include these dependencies as shown below. ```groovy plugins { id 'java' - id 'org.springframework.boot' version '2.5.12' - id 'io.spring.dependency-management' version '1.0.9.RELEASE' + id 'org.springframework.boot' version '3.1.4' + id 'io.spring.dependency-management' version '1.1.3' } +implementation 'com.okta.spring:okta-spring-boot-starter:3.0.5' implementation 'org.springframework.boot:spring-boot-starter-web' -implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' -implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' +implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' +implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' ``` If you are using Maven: @@ -52,11 +53,16 @@ If you are using Maven: org.springframework.boot spring-boot-starter-parent - 2.5.12 + 3.1.5 + + com.okta + okta-spring-boot-starter + 3.0.5 + org.springframework.boot spring-boot-starter-web @@ -71,64 +77,56 @@ If you are using Maven: org.thymeleaf.extras - thymeleaf-extras-springsecurity5 + thymeleaf-extras-springsecurity6 + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect ``` -:::note -The Spring Security 5.4.0 release will include [a fix](https://github.com/spring-projects/spring-security/pull/8357) to validate the issuer claim of the ID token. You should update to this release when available. -::: - ### Configure Spring Security -Spring Security makes it easy to configure your application for authentication with OIDC providers such as Auth0. In your application's configuration, configure the OAuth2 client and provider. The sample below uses an `application.yml` file, though you can also use properties files or any of the other [supported externalization mechanisms](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config). +The Okta Spring Boot Starter makes it easy to configure your application with Auth0. The sample below uses an `application.yml` file, though you can also use properties files or any of the other [supported externalization mechanisms](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config). -:::note -Spring Security will use the `issuer-uri` property value to retrieve all the information necessary to enable login and validation of the ID token at runtime. - -[Additional property mappings](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-boot-property-mappings) are available for further customization, if required. -::: ```yaml # src/main/resources/application.yml -spring: - security: - oauth2: - client: - registration: - auth0: - client-id: ${account.clientId} - client-secret: YOUR_CLIENT_SECRET - scope: - - openid - - profile - - email - provider: - auth0: - # trailing slash is important! - issuer-uri: https://${account.namespace}/ +okta: + oauth2: + issuer: https://${account.namespace}/ + client-id: ${account.clientId} + client-secret: YOUR_CLIENT_SECRET ``` ## Add Login to Your Application -To enable user login with Auth0, create a class that will provide an instance of [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), and add the `@EnableWebSecurity` annotation. +To enable user login with Auth0, create a class that will register a [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), and add the `@Configuration` annotation. ```java package com.auth0.example; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration @EnableWebSecurity public class SecurityConfig { @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http.oauth2Login() - .and().build(); + public SecurityFilterChain configure(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .anyRequest().authenticated() + ) + .oauth2Login(withDefaults()); + return http.build(); } } ``` @@ -137,21 +135,22 @@ public class SecurityConfig { You can further configure the [HttpSecurity](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/builders/HttpSecurity.html) instance to require authentication on all or certain paths. For example, to require authentication on all paths except the home page: ```java -http.authorizeRequests() - .mvcMatchers("/").permitAll() - .anyRequest().authenticated() - .and().oauth2Login(); + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/").permitAll() + .anyRequest().authenticated() + ); ``` ::: -Spring Security will use the client configuration you defined earlier to handle login when a user visits the `/oauth2/authorization/auth0` path of your application. You can use this to create a login link in your application. +The Okta Spring Boot Starter will use the client configuration you defined earlier to handle login when a user visits the `/oauth2/authorization/okta` path of your application. You can use this to create a login link in your application. ```html

You are logged in!

@@ -198,128 +197,71 @@ Auth0 enables the Google social provider by default on new tenants and offers yo ## Add Logout to Your Application -Now that users can log into your application, they need [a way to log out](https://auth0.com/docs/logout/guides/logout-auth0). By default, when logout is enabled, Spring Security will log the user out of your application and clear the session. To enable successful logout of Auth0, you can extend the `SecurityContextLogoutHandler` class to redirect users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://${account.namespace}/v2/logout`) and then immediately redirect them to your application. - -```java -package com.auth0.example; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import org.springframework.stereotype.Controller; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Needed to perform SSO logout with Auth0. By default, Spring will clear the SecurityContext and the session. - * This controller will also log users out of Auth0 by calling the Auth0 logout endpoint. - */ -@Controller -public class LogoutHandler extends SecurityContextLogoutHandler { - - private final ClientRegistrationRepository clientRegistrationRepository; - - /** - * Create a new instance with a {@code ClientRegistrationRepository}, so that we can look up information about the - * configured provider to call the Auth0 logout endpoint. Called by the Spring framework. - * - * @param clientRegistrationRepository the {@code ClientRegistrationRepository} for this application. - */ - @Autowired - public LogoutHandler(ClientRegistrationRepository clientRegistrationRepository) { - this.clientRegistrationRepository = clientRegistrationRepository; - } +Now that users can log into your application, they need [a way to log out](https://auth0.com/docs/logout/guides/logout-auth0). By default, when logout is enabled, Spring Security will log the user out of your application and clear the session. To enable successful logout of Auth0, you can provide a `LogoutHandler` to redirect users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://${account.namespace}/v2/logout`) and then immediately redirect them to your application. - /** - * Delegates to {@linkplain SecurityContextLogoutHandler} to log the user out of the application, and then logs - * the user out of Auth0. - * - * @param httpServletRequest the request. - * @param httpServletResponse the response. - * @param authentication the current authentication. - */ - @Override - public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - Authentication authentication) { - - // Invalidate the session and clear the security context - super.logout(httpServletRequest, httpServletResponse, authentication); - - // Build the URL to log the user out of Auth0 and redirect them to the home page. - // URL will look like https://YOUR-DOMAIN/v2/logout?clientId=YOUR-CLIENT-ID&returnTo=http://localhost:3000 - String issuer = (String) getClientRegistration().getProviderDetails().getConfigurationMetadata().get("issuer"); - String clientId = getClientRegistration().getClientId(); - String returnTo = ServletUriComponentsBuilder.fromCurrentContextPath().build().toString(); - - String logoutUrl = UriComponentsBuilder - .fromHttpUrl(issuer + "v2/logout?client_id={clientId}&returnTo={returnTo}") - .encode() - .buildAndExpand(clientId, returnTo) - .toUriString(); - - try { - httpServletResponse.sendRedirect(logoutUrl); - } catch (IOException ioe) { - // Handle or log error redirecting to logout URL - } - } - - /** - * Gets the Spring ClientRegistration, which we use to get the registered client ID and issuer for building the - * {@code returnTo} query parameter when calling the Auth0 logout API. - * - * @return the {@code ClientRegistration} for this application. - */ - private ClientRegistration getClientRegistration() { - return this.clientRegistrationRepository.findByRegistrationId("auth0"); - } -} -``` - -Next, you need to update your implementation of `SecurityFilterChain` to register your logout handler and specify the request path that should trigger logout (`/logout` in the example below). +In the `SecurityConfig` class, provide a `LogoutHandler` that redirects to the Auth0 logout endpoint, and configure the `HttpSecurity` to add the logout handler: ```java package com.auth0.example; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import java.io.IOException; +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration @EnableWebSecurity public class SecurityConfig { - private final LogoutHandler logoutHandler; + @Value("<%= "${okta.oauth2.issuer}" %>") + private String issuer; + @Value("<%= "${okta.oauth2.client-id}" %>") + private String clientId; - public SecurityConfig(LogoutHandler logoutHandler) { - this.logoutHandler = logoutHandler; + @Bean + public SecurityFilterChain configure(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/", "/images/**").permitAll() + .anyRequest().authenticated() + ) + .oauth2Login(withDefaults()) + + // configure logout with Auth0 + .logout(logout -> logout + .addLogoutHandler(logoutHandler())); + return http.build(); } - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http - .oauth2Login() - .and().logout() - .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) - .addLogoutHandler(logoutHandler) - .and().build(); + private LogoutHandler logoutHandler() { + return (request, response, authentication) -> { + try { + String baseUrl = ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString(); + response.sendRedirect(issuer + "v2/logout?client_id=" + clientId + "&returnTo=" + baseUrl); + } catch (IOException e) { + throw new RuntimeException(e); + } + }; } } ``` -You can then update your view to add a logout link for authenticated users. +You can then update your view to POST to the `/logout` endpoint (Spring Security provides this by default) to enable users to log out. ```html

You are logged in!

- Log Out +
+
``` diff --git a/articles/quickstart/webapp/java-spring-boot/files/application.md b/articles/quickstart/webapp/java-spring-boot/files/application.md index e59bd58b4c..093b036734 100644 --- a/articles/quickstart/webapp/java-spring-boot/files/application.md +++ b/articles/quickstart/webapp/java-spring-boot/files/application.md @@ -3,20 +3,9 @@ name: application.yml language: yaml --- ```yaml -spring: - security: - oauth2: - client: - registration: - auth0: - client-id: ${account.clientId} - client-secret: YOUR_CLIENT_SECRET - scope: - - openid - - profile - - email - provider: - auth0: - # trailing slash is important! - issuer-uri: https://${account.namespace}/ +okta: + oauth2: + issuer: https://${account.namespace}/ + client-id: ${account.clientId} + client-secret: YOUR_CLIENT_SECRET ``` \ No newline at end of file diff --git a/articles/quickstart/webapp/java-spring-boot/files/index.md b/articles/quickstart/webapp/java-spring-boot/files/index.md index 55ac64397b..453bffc798 100644 --- a/articles/quickstart/webapp/java-spring-boot/files/index.md +++ b/articles/quickstart/webapp/java-spring-boot/files/index.md @@ -7,14 +7,16 @@ language: html

You are logged in!

" th:attr="<%= "alt=${profile.get('name')}" %>"/>

">

">

- Log Out +
+
diff --git a/articles/quickstart/webapp/java-spring-boot/files/logout-handler.md b/articles/quickstart/webapp/java-spring-boot/files/logout-handler.md deleted file mode 100644 index 2d13f39567..0000000000 --- a/articles/quickstart/webapp/java-spring-boot/files/logout-handler.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -name: LogoutHandler.java -language: java ---- -```java -package com.auth0.example; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import org.springframework.stereotype.Controller; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Needed to perform SSO logout with Auth0. By default, Spring will clear the SecurityContext and the session. - * This controller will also log users out of Auth0 by calling the Auth0 logout endpoint. - */ -@Controller -public class LogoutHandler extends SecurityContextLogoutHandler { - - private final ClientRegistrationRepository clientRegistrationRepository; - - /** - * Create a new instance with a {@code ClientRegistrationRepository}, so that we can look up information about the - * configured provider to call the Auth0 logout endpoint. Called by the Spring framework. - * - * @param clientRegistrationRepository the {@code ClientRegistrationRepository} for this application. - */ - @Autowired - public LogoutHandler(ClientRegistrationRepository clientRegistrationRepository) { - this.clientRegistrationRepository = clientRegistrationRepository; - } - - /** - * Delegates to {@linkplain SecurityContextLogoutHandler} to log the user out of the application, and then logs - * the user out of Auth0. - * - * @param httpServletRequest the request. - * @param httpServletResponse the response. - * @param authentication the current authentication. - */ - @Override - public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - Authentication authentication) { - - // Invalidate the session and clear the security context - super.logout(httpServletRequest, httpServletResponse, authentication); - - // Build the URL to log the user out of Auth0 and redirect them to the home page. - // URL will look like https://YOUR-DOMAIN/v2/logout?clientId=YOUR-CLIENT-ID&returnTo=http://localhost:3000 - String issuer = (String) getClientRegistration().getProviderDetails().getConfigurationMetadata().get("issuer"); - String clientId = getClientRegistration().getClientId(); - String returnTo = ServletUriComponentsBuilder.fromCurrentContextPath().build().toString(); - - String logoutUrl = UriComponentsBuilder - .fromHttpUrl(issuer + "v2/logout?client_id={clientId}&returnTo={returnTo}") - .encode() - .buildAndExpand(clientId, returnTo) - .toUriString(); - - try { - httpServletResponse.sendRedirect(logoutUrl); - } catch (IOException ioe) { - // Handle or log error redirecting to logout URL - } - } - - /** - * Gets the Spring ClientRegistration, which we use to get the registered client ID and issuer for building the - * {@code returnTo} query parameter when calling the Auth0 logout API. - * - * @return the {@code ClientRegistration} for this application. - */ - private ClientRegistration getClientRegistration() { - return this.clientRegistrationRepository.findByRegistrationId("auth0"); - } -} -``` \ No newline at end of file diff --git a/articles/quickstart/webapp/java-spring-boot/files/security-config-logout.md b/articles/quickstart/webapp/java-spring-boot/files/security-config-logout.md index f061b1eacf..2b60bcd070 100644 --- a/articles/quickstart/webapp/java-spring-boot/files/security-config-logout.md +++ b/articles/quickstart/webapp/java-spring-boot/files/security-config-logout.md @@ -5,29 +5,51 @@ language: java ```java package com.auth0.example; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import java.io.IOException; + +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration @EnableWebSecurity public class SecurityConfig { - private final LogoutHandler logoutHandler; + @Value("<%= "${okta.oauth2.issuer}" %>") + private String issuer; + @Value("<%= "${okta.oauth2.client-id}" %>") + private String clientId; - public SecurityConfig(LogoutHandler logoutHandler) { - this.logoutHandler = logoutHandler; + @Bean + public SecurityFilterChain configure(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/", "/images/**").permitAll() + .anyRequest().authenticated() + ) + .oauth2Login(withDefaults()) + .logout(logout -> logout + .addLogoutHandler(logoutHandler())); + return http.build(); } - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http - .oauth2Login() - .and().logout() - .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) - .addLogoutHandler(logoutHandler) - .and().build(); + private LogoutHandler logoutHandler() { + return (request, response, authentication) -> { + try { + String baseUrl = ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString(); + response.sendRedirect(issuer + "v2/logout?client_id=" + clientId + "&returnTo=" + baseUrl); + } catch (IOException e) { + throw new RuntimeException(e); + } + }; } } + ``` \ No newline at end of file diff --git a/articles/quickstart/webapp/java-spring-boot/files/security-config.md b/articles/quickstart/webapp/java-spring-boot/files/security-config.md index fedd79774a..6c68d3b916 100644 --- a/articles/quickstart/webapp/java-spring-boot/files/security-config.md +++ b/articles/quickstart/webapp/java-spring-boot/files/security-config.md @@ -6,17 +6,25 @@ language: java package com.auth0.example; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http.oauth2Login() - .and().build(); + http + .authorizeHttpRequests(authorize -> authorize + .anyRequest().authenticated() + ) + .oauth2Login(withDefaults()); + return http.build(); } } ``` \ No newline at end of file diff --git a/articles/quickstart/webapp/java-spring-boot/index.yml b/articles/quickstart/webapp/java-spring-boot/index.yml index 8d84684b90..7674acadc2 100644 --- a/articles/quickstart/webapp/java-spring-boot/index.yml +++ b/articles/quickstart/webapp/java-spring-boot/index.yml @@ -21,13 +21,16 @@ articles: show_steps: true hidden_articles: - "interactive" +sdk: + name: Okta Spring Boot Starter + url: https://github.com/okta/okta-spring-boot/ + logo: spring github: org: auth0-samples repo: auth0-spring-boot-login-samples branch: master requirements: - - Java 8 - - Gradle 6 or Maven 3 + - Java 17 next_steps: - path: 01-login list: diff --git a/articles/quickstart/webapp/java-spring-boot/interactive.md b/articles/quickstart/webapp/java-spring-boot/interactive.md index 087a9f5674..cbf7facf03 100644 --- a/articles/quickstart/webapp/java-spring-boot/interactive.md +++ b/articles/quickstart/webapp/java-spring-boot/interactive.md @@ -1,13 +1,12 @@ --- title: Add login to your Spring Webapp -description: Spring Boot and Spring Security support OIDC natively, enabling you to add authentication to your application without the need for any additional libraries. This guide demonstrates how to integrate Auth0 with any new or existing Spring Boot 2 web application. +description: The Okta Spring Boot Starter makes it easy to add login to your Spring Boot application. interactive: true files: - files/application - files/security-config - files/index - files/home-controller - - files/logout-handler - files/security-config-logout github: path: mvc-login @@ -20,7 +19,7 @@ This tutorial uses [Spring MVC](https://docs.spring.io/spring/docs/current/sprin ::: <%= include('../../_includes/_configure_auth0_interactive', { - callback: 'http://localhost:3000/login/oauth2/code/auth0', + callback: 'http://localhost:3000/login/oauth2/code/okta', returnTo: 'http://localhost:3000' }) %> @@ -28,7 +27,7 @@ This tutorial uses [Spring MVC](https://docs.spring.io/spring/docs/current/sprin ### Add Spring dependencies -Spring Boot provides a `spring-boot-starter-oauth2-client` starter, which provides all the Spring Security dependencies needed to add authentication to your web application. +To integrate your Spring Boot application with Auth0, include the [Okta Spring Boot Starter](https://github.com/okta/okta-spring-boot/) in your application's dependencies. :::note This guide uses [Thymeleaf](https://www.thymeleaf.org/) and the [Spring Security integration module](https://github.com/thymeleaf/thymeleaf-extras-springsecurity) for the view layer. If you are using a different view technology, the Spring Security configuration and components remain the same. @@ -39,16 +38,15 @@ If you're using Gradle, you can include these dependencies as shown below. ```groovy plugins { id 'java' - id 'org.springframework.boot' version '2.5.12' - id 'io.spring.dependency-management' version '1.0.9.RELEASE' + id 'org.springframework.boot' version '3.1.4' + id 'io.spring.dependency-management' version '1.1.3' } -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' -} +implementation 'com.okta.spring:okta-spring-boot-starter:3.0.5' +implementation 'org.springframework.boot:spring-boot-starter-web' +implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' +implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' +implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' ``` If you are using Maven: @@ -57,11 +55,16 @@ If you are using Maven: org.springframework.boot spring-boot-starter-parent - 2.5.12 + 3.1.4 + + com.okta + okta-spring-boot-starter + 3.0.5 + org.springframework.boot spring-boot-starter-web @@ -76,45 +79,49 @@ If you are using Maven: org.thymeleaf.extras - thymeleaf-extras-springsecurity5 + thymeleaf-extras-springsecurity6 + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect ``` -:::note -The Spring Security 5.4.0 release includes [a fix](https://github.com/spring-projects/spring-security/pull/8357) to validate the ID token issuer claim. Upgrade to 5.4.0 or higher when possible. -::: +## Configure Spring Security {{{ data-action=code data-code="application.yml#1:11" }}} -## Configure Spring Security {{{ data-action=code data-code="application.yml#1:16" }}} +The Okta Spring Boot Starter makes it easy to configure your application with Auth0. The sample below uses an `application.yml` file, though you can also use properties files or any of the other [supported externalization mechanisms](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config). -Spring Security makes it easy to configure your application for authentication with OIDC providers such as Auth0. In your application's configuration, configure the OAuth2 client and provider. The sample to the right shows an `application.yml` file, though you can also use properties files or any of the other [supported externalization mechanisms](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config). -:::note -Spring Security uses the `issuer-uri` property value to retrieve the information necessary to enable login and ID token validation at runtime. - -If you need more property mappings, [review the Spring documentation](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-boot-property-mappings) for further customization. -::: +```yaml +# src/main/resources/application.yml +okta: + oauth2: + issuer: https://${account.namespace}/ + client-id: ${account.clientId} + client-secret: YOUR_CLIENT_SECRET +``` ## Add login to your application {{{ data-action=code data-code="SecurityConfig.java" }}} -To enable user login with Auth0, create a class that will provide an instance of [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), and add the `@EnableWebSecurity` annotation. +To enable user login with Auth0, create a class that will register a [SecurityFilterChain](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/SecurityFilterChain.html), and add the `@Configuration` annotation. -Later in this quickstart, you will overwrite this file with `SecurityConfigWithLogout.java` to provide extra configurations to support the logout feature. :::note You can configure the [HttpSecurity](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/builders/HttpSecurity.html) instance to require authentication on all or certain paths. For example, to require authentication on all paths except the home page: ```java -http.authorizeRequests() - .mvcMatchers("/").permitAll() - .anyRequest().authenticated() - .and().oauth2Login(); + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/").permitAll() + .anyRequest().authenticated() + ); ``` ::: ## Add front page {{{ data-action=code data-code="index.html" }}} -Spring Security uses the client configuration you defined earlier to handle login when a user visits the `/oauth2/authorization/auth0` path of your application. You can use this to create a login link in your application. +The Okta Spring Boot Starter will use the client configuration you defined earlier to handle login when a user visits the `/oauth2/authorization/okta` path of your application. You can use this to create a login link in your application. This page returns the user attributes when the user authentications. You will use the `/logout` link in the template to implement the logout feature. @@ -133,7 +140,7 @@ When you click the login link, verify the application redirects you to the [Auth :::checkpoint-failure If your application did not allow login or signup: * Verify you configured the correct Callback URL -* Verify you added the login link to redirect to `/oauth2/authorization/auth0` +* Verify you added the login link to redirect to `/oauth2/authorization/okta` Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. @@ -147,15 +154,11 @@ Still having issues? Check out our [documentation](https://auth0.com/docs) or vi Auth0 enables the Google social provider by default on new tenants and offers you developer keys to test logging in with [social identity providers](https://auth0.com/docs/connections/identity-providers-social). However, these developer keys have some limitations that may cause your application to behave differently. For more details on what this behavior may look like and how to fix it, consult the [Test Social Connections with Auth0 Developer Keys](https://auth0.com/docs/connections/social/devkeys#limitations-of-developer-keys) document. ::: -## Add logout to your application {{{ data-action=code data-code="LogoutHandler.java" }}} - -Now that users can log into your application, they need [a way to log out](https://auth0.com/docs/logout/guides/logout-auth0). By default, Spring Security logs user out of your application and clears the session when you enable logout. To enable successful Auth0 logout, extend the `SecurityContextLogoutHandler` class to redirect users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://${account.namespace}/v2/logout`) and then immediately redirect them to your application. - -## Update your security configuration {{{ data-action=code data-code="SecurityConfigWithLogout.java" }}} +## Add logout to your application {{{ data-action=code data-code="SecurityConfigWithLogout.java" }}} -Next, update your implementation of `SecurityFilterChain` to register your logout handler and specify the request path that should trigger logout (`/logout` in the example below). +Now that users can log into your application, they need [a way to log out](https://auth0.com/docs/logout/guides/logout-auth0). By default, when logout is enabled, Spring Security will log the user out of your application and clear the session. To enable successful logout of Auth0, you can provide a `LogoutHandler` to redirect users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://${account.namespace}/v2/logout`) and then immediately redirect them to your application. -You can remove the `SecurityConfig.java` and replace it with `SecurityConfigWithLogout.java` or update the contents from the one file to another. +In the `SecurityConfig` class, provide a `LogoutHandler` that redirects to the Auth0 logout endpoint, and configure the `HttpSecurity` to add the logout handler ::::checkpoint @@ -166,7 +169,7 @@ When you click logout link, the application should redirect you to the address y :::checkpoint-failure If your application did not allow logout: * Verify you configured the correct logout URL -* Verify you added the logout link to redirect to `/logout` +* Verify you added the logout link to POST to `/logout` Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help. diff --git a/articles/quickstart/webapp/nextjs/01-login.md b/articles/quickstart/webapp/nextjs/01-login.md index 80cb7b4656..f23cd7ec60 100644 --- a/articles/quickstart/webapp/nextjs/01-login.md +++ b/articles/quickstart/webapp/nextjs/01-login.md @@ -68,6 +68,10 @@ This creates the following routes: - `/api/auth/callback`: The route Auth0 will redirect the user to after a successful login. - `/api/auth/me`: The route to fetch the user profile from. +::: note +This QuickStart targets the Next.js [App Router](https://nextjs.org/docs/app). If you're using the [Pages Router](https://nextjs.org/docs/pages), check out the example in the SDK's [README](https://github.com/auth0/nextjs-auth0#page-router). +::: + ### Add the `UserProvider` component On the frontend side, the SDK uses React Context to manage the authentication state of your users. To make that state available to all your pages, you need to override the [Root Layout component](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#root-layout-required) and wrap the `` tag with a `UserProvider` in the file `app/layout.jsx`. diff --git a/articles/quickstart/webapp/nextjs/interactive.md b/articles/quickstart/webapp/nextjs/interactive.md index 8cff7ed8ee..e792e7b77b 100644 --- a/articles/quickstart/webapp/nextjs/interactive.md +++ b/articles/quickstart/webapp/nextjs/interactive.md @@ -56,6 +56,10 @@ The SDK will read these values from the Node.js process environment and automati ## Add the dynamic Route Handler {{{ data-action=code data-code="app/api/auth/[auth0]/route.js" }}} +::: note +This QuickStart targets the Next.js [App Router](https://nextjs.org/docs/app). If you're using the [Pages Router](https://nextjs.org/docs/pages), check out the example in the SDK's [README](https://github.com/auth0/nextjs-auth0#page-router). +::: + Create a file at `app/api/auth/[auth0]/route.js`. This is your Route Handler file with a [Dynamic Route Segment](https://nextjs.org/docs/app/building-your-application/routing/route-handlers#dynamic-route-segments). Then, import in that file the `handleAuth` method from the SDK, and export the result of calling it from the `GET` export. This creates the following routes: diff --git a/config/redirects.js b/config/redirects.js index eb0e04b979..81a2b670c3 100644 --- a/config/redirects.js +++ b/config/redirects.js @@ -308,6 +308,14 @@ const redirects = [ from: '/xamarin-tutorial', to: '/quickstart/native/xamarin', }, + { + from: '/quickstart/native/xamarin', + to: '/quickstart/native/net-android-ios', + }, + { + from: '/quickstart/native/xamarin/interactive', + to: '/quickstart/native/net-android-ios/interactive', + }, { from: '/quickstart/spa/auth0-react/02', to: '/quickstart/spa/react/02-calling-an-api', @@ -951,6 +959,11 @@ const redirects = [ }, /* MICROSITES */ + { + from: ['/microsites/call-api/call-api-m2m-app'], + to: '/get-started/authentication-and-authorization-flow/client-credentials-flow', + + }, /* ARCHITECTURE SCENARIOS */ @@ -4038,16 +4051,21 @@ const redirects = [ to: '/deploy-monitor/deploy-cli-tool', }, { - from: ['/deploy-monitor/auth0-deploy-cli/configuring-the-deploy-cli'], - to: '/deploy-monitor/deploy-cli-tool/configuring-the-deploy-cli', + from: ['/deploy-monitor/auth0-deploy-cli/configuring-the-deploy-cli', + '/deploy-monitor/deploy-cli-tool/configuring-the-deploy-cli', + ], + to: '/deploy-monitor/deploy-cli-tool/configure-the-deploy-cli', }, { - from: ['/deploy-monitor/deploy-cli-tool/call-deploy-cli-tool-programmatically'], - to: '/deploy-monitor/deploy-cli-tool/using-as-a-node-module', + from: ['/deploy-monitor/deploy-cli-tool/call-deploy-cli-tool-programmatically', + '/deploy-monitor/deploy-cli-tool/using-as-a-node-module',], + to: '/deploy-monitor/deploy-cli-tool/use-as-a-node-module', }, { - from: ['/deploy-monitor/deploy-cli-tool/incorporate-deploy-cli-into-build-environment'], - to: '/deploy-monitor/deploy-cli-tool/incorporating-into-multi-environment-workflows', + from: ['/deploy-monitor/deploy-cli-tool/incorporate-deploy-cli-into-build-environment', + '/deploy-monitor/deploy-cli-tool/incorporating-into-multi-environment-workflows', + ], + to: '/deploy-monitor/deploy-cli-tool/incorporate-into-multi-environment-workflows', }, { from: ['/deploy-monitor/deploy-cli-tool/import-export-tenant-configuration-to-yaml-file'], @@ -4062,8 +4080,10 @@ const redirects = [ to: '/deploy-monitor/deploy-cli-tool/keyword-replacement', }, { - from: ['/deploy-monitor/deploy-cli-tool/deploy-cli-tool-options'], - to: '/deploy-monitor/deploy-cli-tool/using-as-a-cli', + from: ['/deploy-monitor/deploy-cli-tool/deploy-cli-tool-options', + '/deploy-monitor/deploy-cli-tool/using-as-a-cli', + ], + to: '/deploy-monitor/deploy-cli-tool/use-as-a-cli', }, { from: ['/deploy-monitor/deploy-cli-tool/auth0-terraform-provider'], @@ -4073,6 +4093,10 @@ const redirects = [ from: ['/deploy-monitor/deploy-cli-tool/how-to-contribute'], to: '/deploy-monitor/deploy-cli-tool', }, + { + from: ['/deploy-monitor/deploy-cli-tool/excluding-resources-from-management'], + to: '/deploy-monitor/deploy-cli-tool/exclude-resources-from-management', + }, /* Extensions */ @@ -7825,8 +7849,10 @@ const redirects = [ '/policies/rate-limits-api', '/policies/authentication-api-endpoint-rate-limits', '/support/policies/rate-limit-policy/authentication-api-endpoint-rate-limits', + '/troubleshoot/customer-support/operational-policies/rate-limit-policy/authentication-api-endpoint-rate-limits', + ], - to: '/troubleshoot/customer-support/operational-policies/rate-limit-policy/authentication-api-endpoint-rate-limits', + to: '/troubleshoot/customer-support/operational-policies/rate-limit-policy', }, { from: [ @@ -7835,8 +7861,9 @@ const redirects = [ '/policies/rate-limits-mgmt-api', '/policies/management-api-endpoint-rate-limits', '/support/policies/rate-limit-policy/management-api-endpoint-rate-limits', + '/troubleshoot/customer-support/operational-policies/rate-limit-policy/management-api-endpoint-rate-limits', ], - to: '/troubleshoot/customer-support/operational-policies/rate-limit-policy/management-api-endpoint-rate-limits', + to: '/troubleshoot/customer-support/operational-policies/rate-limit-policy', }, { from: [ @@ -7845,8 +7872,15 @@ const redirects = [ '/connections/database/rate-limits', '/support/policies/database-connections-rate-limits', '/support/policies/rate-limit-policy/database-connections-rate-limits', + '/troubleshoot/customer-support/operational-policies/rate-limit-policy/database-connections-rate-limits', ], - to: '/troubleshoot/customer-support/operational-policies/rate-limit-policy/database-connections-rate-limits', + to: '/troubleshoot/customer-support/operational-policies/rate-limit-policy', + }, + { + from: [ + '/troubleshoot/customer-support/operational-policies/rate-limit-policy/understand-rate-limit-burst-capability', + ], + to: '/troubleshoot/customer-support/operational-policies/rate-limit-policy', }, { from: [ diff --git a/snippets/native-platforms/xamarin/dependencies.md b/snippets/native-platforms/xamarin/dependencies.md index 5f34c8e786..10c16887f3 100644 --- a/snippets/native-platforms/xamarin/dependencies.md +++ b/snippets/native-platforms/xamarin/dependencies.md @@ -1,9 +1,9 @@ -If you are using Visual Studio 2017, simply open the Package Manager Console (View -> Other Windows -> Package Manager Console), and install the package: +If you are using Visual Studio, simply open the Package Manager Console (View -> Other Windows -> Package Manager Console), and install the package: **For Android:** ```text -Install-Package Auth0.OidcClient.Android +Install-Package Auth0.OidcClient.AndroidX ``` **For iOS:** @@ -15,5 +15,5 @@ Install-Package Auth0.OidcClient.iOS Alternatively, if you are using Visual Studio for Mac, please perform the following steps: 1. With the project loaded in Visual Studio for Mac, Ctrl+click (or right click) on the **Packages** folder of the project in the **Solution Pad**, and select **Add Packages...** - 2. The **Add Packages** dialog will appear. Search and locate the package called `Auth0.OidcClient.Android` or `Auth0.OidcClient.iOS` depending on your platform. + 2. The **Add Packages** dialog will appear. Search and locate the package called `Auth0.OidcClient.AndroidX` or `Auth0.OidcClient.iOS` depending on your platform. 3. Tick the checkbox next to the package to select it, and click the **Add Package** button \ No newline at end of file