Skip to content

Commit 5201327

Browse files
authored
Merge pull request #96283 from MicrosoftDocs/master
11/18 AM Publish
2 parents 28688c6 + 83845c0 commit 5201327

File tree

84 files changed

+1828
-1262
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+1828
-1262
lines changed

articles/active-directory/develop/authentication-scenarios.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ This attribute causes ASP.NET to check for the presence of a session cookie cont
145145
### How a web app delegates sign-in to Azure AD and obtains a token
146146

147147
User authentication happens via the browser. The OpenID protocol uses standard HTTP protocol messages.
148-
- The web app sends an HTTP 202 (redirect) to the browser to use Azure AD.
148+
- The web app sends an HTTP 203 (redirect) to the browser to use Azure AD.
149149
- When the user is authenticated, Azure AD sends the token to the web app by using a redirect through the browser.
150150
- The redirect is provided by the web app in the form of a redirect URI. This redirect URI is registered with the Azure AD application object. There can be several redirect URIs because the application may be deployed at several URLs. So the web app will also need to specify the redirect URi to use.
151151
- Azure AD verifies that the redirect URI sent by the web app is one of the registered redirect URIs for the app.
@@ -156,7 +156,7 @@ The flow described above applies, with slight differences, to desktop and mobile
156156

157157
Desktop and mobile applications can use an embedded Web control, or a system browser, for authentication. The following diagram shows how a Desktop or mobile app uses the Microsoft authentication library (MSAL) to acquire access tokens and call web APIs.
158158

159-
![Desktop app how it appears to be](media/authentication-scenarios/web-app-how-it-appears-to-be.png)
159+
![Desktop app how it appears to be](media/authentication-scenarios/desktop-app-how-it-appears-to-be.png)
160160

161161
MSAL uses a browser to get tokens, and as with web apps, delegates authentication to Azure AD.
162162

59.6 KB
Loading

articles/active-directory/develop/msal-net-client-assertions.md

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ ms.devlang: na
1414
ms.topic: conceptual
1515
ms.tgt_pltfrm: na
1616
ms.workload: identity
17-
ms.date: 07/16/2019
17+
ms.date: 11/18/2019
1818
ms.author: jmprieur
1919
ms.reviewer:
2020
ms.custom: aaddev
@@ -23,6 +23,7 @@ ms.collection: M365-identity-device-management
2323
---
2424

2525
# Confidential client assertions
26+
2627
In order to prove their identity, confidential client applications exchange a secret with Azure AD. The secret can be:
2728
- A client secret (application password).
2829
- A certificate, which is used to build a signed assertion containing standard claims.
@@ -35,6 +36,9 @@ MSAL.NET has four methods to provide either credentials or assertions to the con
3536
- `.WithClientAssertion()`
3637
- `.WithClientClaims()`
3738

39+
> [!NOTE]
40+
> While it is possible to use the `WithClientAssertion()` API to acquire tokens for the confidential client, we do not recommend using it by default as it is more advanced and is designed to handle very specific scenarios which are not common. Using the `.WithCertificate()` API will allow MSAL.NET to handle this for you. This api offers you the ability to customize your authentication request if needed but the default assertion created by `.WithCertificate()` will suffice for most authentication scenarios. This API can also be used as a workaround in some scenarios where MSAL.NET fails to perform the signing operation internally.
41+
3842
### Signed assertions
3943

4044
A signed client assertion takes the form of a signed JWT with the payload containing the required authentication claims mandated by Azure AD, Base64 encoded. To use it:
@@ -63,9 +67,9 @@ Here is an example of how to craft these claims:
6367
private static IDictionary<string, string> GetClaims()
6468
{
6569
//aud = https://login.microsoftonline.com/ + Tenant ID + /v2.0
66-
string aud = "https://login.microsoftonline.com/72f988bf-86f1-41af-hd4m-2d7cd011db47/v2.0";
70+
string aud = $"https://login.microsoftonline.com/{tenantId}/v2.0";
6771

68-
string ConfidentialClientID = "61dab2ba-145d-4b1b-8569-bf4b9aed5dhb" //client id
72+
string ConfidentialClientID = "00000000-0000-0000-0000-000000000000" //client id
6973
const uint JwtToAadLifetimeInSeconds = 60 * 10; // Ten minutes
7074
DateTime validFrom = DateTime.UtcNow;
7175
var nbf = ConvertToTimeT(validFrom);
@@ -102,11 +106,11 @@ string Encode(byte[] arg)
102106
return s;
103107
}
104108

105-
string GetAssertion()
109+
string GetSignedClientAssertion()
106110
{
107111
//Signing with SHA-256
108112
string rsaSha256Signature = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
109-
X509Certificate2 certificate = ReadCertificate(config.CertificateName);
113+
X509Certificate2 certificate = new X509Certificate2("Certificate.pfx", "Password", X509KeyStorageFlags.EphemeralKeySet);
110114

111115
//Create RSACryptoServiceProvider
112116
var x509Key = new X509AsymmetricSecurityKey(certificate);
@@ -126,11 +130,57 @@ string GetAssertion()
126130
string token = Encode(Encoding.UTF8.GetBytes(JObject.FromObject(header).ToString())) + "." + Encode(Encoding.UTF8.GetBytes(JObject.FromObject(GetClaims())));
127131

128132
string signature = Encode(rsa.SignData(Encoding.UTF8.GetBytes(token), new SHA256Cng()));
129-
string SignedAssertion = string.Concat(token, ".", signature);
130-
return SignedAssertion;
133+
string signedClientAssertion = string.Concat(token, ".", signature);
134+
return signedClientAssertion;
131135
}
132136
```
133137

138+
### Alternative method
139+
140+
You also have the option of using [Microsoft.IdentityModel.JsonWebTokens](https://www.nuget.org/packages/Microsoft.IdentityModel.JsonWebTokens/) to create the assertion for you. The code will be a more elegant as shown in the example below:
141+
142+
```CSharp
143+
string GetSignedClientAssertion()
144+
{
145+
var cert = new X509Certificate2("Certificate.pfx", "Password", X509KeyStorageFlags.EphemeralKeySet);
146+
147+
//aud = https://login.microsoftonline.com/ + Tenant ID + /v2.0
148+
string aud = $"https://login.microsoftonline.com/{tenantID}/v2.0";
149+
150+
// client_id
151+
string confidentialClientID = "00000000-0000-0000-0000-000000000000";
152+
153+
// no need to add exp, nbf as JsonWebTokenHandler will add them by default.
154+
var claims = new Dictionary<string, object>()
155+
{
156+
{ "aud", aud },
157+
{ "iss", confidentialClientID },
158+
{ "jti", Guid.NewGuid().ToString() },
159+
{ "sub", confidentialClientID }
160+
};
161+
162+
var securityTokenDescriptor = new SecurityTokenDescriptor
163+
{
164+
Claims = claims,
165+
SigningCredentials = new X509SigningCredentials(cert)
166+
};
167+
168+
var handler = new JsonWebTokenHandler();
169+
var signedClientAssertion = handler.CreateToken(securityTokenDescriptor);
170+
}
171+
```
172+
173+
Once you have your signed client assertion, you can use it with the MSAL apis as shown below.
174+
175+
```CSharp
176+
string signedClientAssertion = GetSignedClientAssertion();
177+
178+
var confidentialApp = ConfidentialClientApplicationBuilder
179+
.Create(ConfidentialClientID)
180+
.WithClientAssertion(signedClientAssertion)
181+
.Build();
182+
```
183+
134184
### WithClientClaims
135185

136186
`WithClientClaims(X509Certificate2 certificate, IDictionary<string, string> claimsToSign, bool mergeWithDefaultClaims = true)` by default will produce a signed assertion containing the claims expected by Azure AD plus additional client claims that you want to send. Here is a code snippet on how to do that.

0 commit comments

Comments
 (0)