Search code examples
azure-active-directoryopenid-connectowinazure-app-registration

Able to use App Registration without client secret


I've been working through transitioning an old webforms app to use Azure AD authentication, everything is working fine however I noticed that although I added a client secret to the app registration, my web app is able to authenticate without passing the client secret.

Is this normal behavior? I'm probably missing something simple here but I was under the impression that creating a client secret means that auth requests to this app reg must include the client secret otherwise Azure AD would assume the request has come from an unauthorized app.

In my StartupAuth I'm simply just ommitting the client secret (deliberately for testing purposes)

app.UseOpenIdConnectAuthentication(New OpenIdConnectAuthenticationOptions() With {
        .ClientId = clientId,
        .Authority = authority,
        .RedirectUri = redirectUri,
        .PostLogoutRedirectUri = postLogoutRedirectUri,
        .Notifications = New OpenIdConnectAuthenticationNotifications() With {
            .AuthenticationFailed = Function(context) System.Threading.Tasks.Task.FromResult(0),
            .SecurityTokenValidated = Function(context)
                                          Return OnSecurityTokenValidated(context)
                                      End Function
        }}
    )

I'm able to get an ID token without providing the client secret but I was expecting it to reject the request.


Solution

  • Using the authorization code flow, starts with requesting an authorization code for a user. This process authenticates the user and let's you know the user is who they say they are, and is where they would authorize any access requested by your app (if it contains permissions for reading their user profile for example). This is the section circled in green in the image below. This step does not appear to require any client secret since it doesn't actually give your app client access to resources on that user's behalf unless you also have the app client secret/cert to use for the access token later.

    After authentication, if you want to do anything as that user (call a Web API as that user for example), then you need an access token and that is where you have to use the authorization code from the first step plus your app client secret/cert to get the access token. This is the section circled in red below.

    https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#protocol-details

    enter image description here

    If you are just authenticating the client and never actually need to access resources on behalf of that user, then you would not need to use your AAD app client secret. I wasn't able to find any official Microsoft documentation that explicitly states this, and the closest I found was: https://auth0.com/docs/get-started/authentication-and-authorization-flow/hybrid-flow which states:

    If your application only needs to use Hybrid Flow for sign-on, you will not need a Refresh Token or an Access Token, only an ID Token with claims.

    This is also implied in the docs here, where the client secret/cert isn't mentioned until the access token section: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#redeem-a-code-for-an-access-token Also note that certificate credentials are preferred over client secrets.

    Redeem a code for an access token All confidential clients have a choice of using client secrets or certificate credentials. Symmetric shared secrets are generated by the Microsoft identity platform. For best security, we recommend using certificate credentials. Public clients, which include native applications and single page apps, must not use secrets or certificates when redeeming an authorization code. Always ensure that your redirect URIs include the type of application and are unique.