For server guided ad insertion, your app makes an ad pod manifest request.
For more information, see [Generate the ad pod manifest URL](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/live/get-started/sgai#generate-ad-pod-manifest-url).

This page covers authenticating pod manifest requests using Hash-Based Message Authentication Code (HMAC) tokens.

## Before you begin

Before you continue, do the following:

- Complete the [prerequisites](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/live/pod-request-overview#prerequisites).
- Ensure you've enabled the Pod resource authentication keys in your livestream event in your [Google Ad Manager Account](https://admanager.google.com).

### Generate an HMAC token

To generate a token, do the following:

1. Collect the path and query parameters (except auth-token) populated for your pod manifest request. For a full list, see [Method: HLS pod manifest](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_hls_pod_manifest) or [Method: DASH pod manifest](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_dash_pod_manifest).
2. Combine your parameter key and value strings. You must sort the parameters alphabetically
   and separate the parameters with the tilde `~` character, for example:

       ad_break_id=AD_BREAK_ID~custom_asset_key=CUSTOM_ASSET_KEY~exp=EXPIRATION~network_code=NETWORK_CODE~pd=POD_DURATION

3. Calculate a SHA-256 hash of the token string using your DAI authentication key.

4. Format the hash output in hexadecimal.

5. To sign the token string, append the signature at the end of the parameters you gathered earlier:

       ad_break_id=...~hmac=HMAC_SIGNATURE`

   Replace the `HMAC_SIGNATURE` with the signature you generated by
   hashing the token string using your DAI authentication key.
6. To pass the signed token string safely, apply URL-encoding to the signed token string.

The following example generates the URL-encoded value of a signed token string:

### HLS

    # Add 60 seconds to the current time
    future_epoch=$((EPOCHSECONDS + 60))

    echo "Current: $EPOCHSECONDS"
    echo "Future: $future_epoch"
    # Current: 1774464277
    # Future: 1774464337

    # Sample DAI pod resource authentication key
    key="EB089..."

    # Sort parameters in the token string
    token="ad_break_id=ab-001~custom_asset_key=hls-pod-serving-manifest-auth-stream-pod~exp=1774464337~network_code=21775744923~pd=30000"

    # Generate the token's signature.
    echo -n $token | openssl dgst -sha256 -mac HMAC -macopt key:$key

    # SHA2-256(stdin)= 68ce65522e0b5f0b4e9a842a0a300e5cba8d14502268b18f66619abcc4dc016e

    # Sign the token: ad_break_id=ab-001~custom_asset_key=hls-pod-serving-manifest-auth-stream-pod~exp=1774464337~network_code=21775744923~pd=30000~hmac=68ce65522e0b5f0b4e9a842a0a300e5cba8d14502268b18f66619abcc4dc016e

    # Encode the token:
    ad_break_id%3Dab-001~custom_asset_key%3Dhls-pod-serving-manifest-auth-stream-pod~exp%3D1774464337~network_code%3D21775744923~pd%3D30000~hmac%3D68ce65522e0b5f0b4e9a842a0a300e5cba8d14502268b18f66619abcc4dc016e

### DASH

    # Add 60 seconds to the current time
    future_epoch=$((EPOCHSECONDS + 60))

    echo "Current: $EPOCHSECONDS"
    echo "Future: $future_epoch"
    # Current: 1774464770
    # Future: 1774464830

    # Sample DAI pod resource authentication key
    key="EB08..."

    # Assemble parameters in the token string
    token="ad_break_id=ab-001~custom_asset_key=dash-pod-serving-manifest-auth-stream-pod~exp=1774464830~network_code=21775744923~pd=30000"

    # Generate the token's signature.
    echo -n $token | openssl dgst -sha256 -mac HMAC -macopt key:$key

    # SHA2-256(stdin)= 51ce9544b2f04a27d5a818bd982c262f97b7bc64d9e8ea07d13ae73e04062614

    # Sign the token: ad_break_id=ab-001~custom_asset_key=dash-pod-serving-manifest-auth-stream-pod~exp=1774464830~network_code=21775744923~pd=30000~hmac=51ce9544b2f04a27d5a818bd982c262f97b7bc64d9e8ea07d13ae73e04062614

    # Encode the token: ad_break_id%3Dab-001~custom_asset_key%3Ddash-pod-serving-manifest-auth-stream-pod~exp%3D1774464830~network_code%3D21775744923~pd%3D30000~hmac%3D51ce9544b2f04a27d5a818bd982c262f97b7bc64d9e8ea07d13ae73e04062614

### Authenticate a pod manifest request

To authenticate your pod manifest requests, use the `auth-token` query string
parameter to pass the URL-encoded signed HMAC token.

### HLS

The following example uses an HMAC token to authenticate an HLS pod manifest
request:

    curl --include "https://dai.google.com/linear/pods/v1/hls/network/21775744923/custom_asset/hls-pod-serving-manifest-auth-stream-pod/ad_break_id/ab-001.m3u8?stream_id=381c29ff-9015-4f9f-8a43-e2e13822473a:ATL&pd=30000&auth-token=ad_break_id%3Dab-001~custom_asset_key%3Dhls-pod-serving-manifest-auth-stream-pod~exp%3D1774464337~network_code%3D21775744923~pd%3D30000~hmac%3D68ce65522e0b5f0b4e9a842a0a300e5cba8d14502268b18f66619abcc4dc016e"

If successful, you see the following response:

    ...
    < HTTP/2 200
    < vary: Accept-Encoding
    <
    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-MEDIA:TYPE=AUDIO,URI="https://dai.google.com/linear/pods/v1/hls/event/o35L8Xl8TFa2naph5beXsw/ab_break_id/ab-001/profile/fmp4-audio-128kbps.m3u8?pd=30000&stream_id=9331d770-ae82-460a-96d4-b971eb6f8fa0%3ADLS",GROUP-ID="AUDIO",NAME="mp4a.40.2-0",DEFAULT=YES
    #EXT-X-STREAM-INF:BANDWIDTH=1268994,RESOLUTION=1280x720,CODECS="avc1.64001e,mp4a.40.2",AUDIO="AUDIO"
    https://dai.google.com/linear/pods/v1/hls/event/o35L8Xl8TFa2naph5beXsw/ad_break_id/ab-001/profile/Video-1200k.m3u8?pd=30000&stream_id=9331d770-ae82-460a-96d4-b971eb6f8fa0%3ADLS
    #EXT-X-STREAM-INF:BANDWIDTH=5114591,RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2",AUDIO="AUDIO"
    ...

To understand the response structure and status codes, refer to [Method: HLS pod manifest](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_hls_pod_manifest).

If authentication fails, you see the `x-ad-manager-dai-warning`:

    ...
    < HTTP/2 200
    < x-ad-manager-dai-warning: Unable to create ad break due to Unauthorized error (skipping ad break creation)
    ....
    <
    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-MEDIA:TYPE=AUDIO,URI="https://dai.google.com/linear/pods/v1/hls/event/o35L8Xl8TFa2naph5beXsw/ad_break_id/ab-001/profile/fmp4-audio-128kbps.m3u8?pd=30000&stream_id=381c29ff-9015-4f9f-8a43-e2e13822473a%3AATL",GROUP-ID="AUDIO",NAME="mp4a.40.2-0",DEFAULT=YES
    #EXT-X-STREAM-INF:BANDWIDTH=1268994,RESOLUTION=1280x720,CODECS="avc1.64001e,mp4a.40.2",AUDIO="AUDIO"
    https://dai.google.com/linear/pods/v1/hls/event/o35L8Xl8TFa2naph5beXsw/ad_break_id/ab-001/profile/Video-1200k.m3u8?pd=30000&stream_id=381c29ff-9015-4f9f-8a43-e2e13822473a%3AATL
    #EXT-X-STREAM-INF:BANDWIDTH=5114591,RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2",AUDIO="AUDIO"
    https://dai.google.com/linear/pods/v1/hls/event/o35L8Xl8TFa2naph5beXsw/ad_break_id/ab-001/profile/media-ts-4628000bps.m3u8?pd=30000&stream_id=381c29ff-9015-4f9f-8a43-e2e13822473a%3AATL

### DASH

The following example uses an HMAC token to authenticate a DASH pod manifest
request:

    curl --include "https://dai.google.com/linear/pods/v1/dash/network/21775744923/custom_asset/dash-pod-serving-manifest-auth-stream-pod/stream/310b1882-4a62-436a-99b1-ca56435b48f6:TUL/ad_break_id/ab-001/manifest.mpd?pd=30000&auth-token=ad_break_id%3Dab-001~custom_asset_key%3Ddash-pod-serving-manifest-auth-stream-pod~exp%3D1774464830~network_code%3D21775744923~pd%3D30000~hmac%3D51ce9544b2f04a27d5a818bd982c262f97b7bc64d9e8ea07d13ae73e04062614"

If successful, you see the following response:

    ...
    HTTP/2 200
    <?xml version="1.0" encoding="UTF-8"?>
    <MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:_XMLSchema-instance="http://www.w3.org/2001/XMLSchema-instance" _XMLSchema-instance:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" id="201" profiles="urn:hbbtv:dash:profile:isoff-live:2012" type="static" mediaPresentationDuration="PT30S" minBufferTime="PT2S">
    <Period id="1" duration="PT30S">
      <BaseURL>https://dai.google.com/linear/pods/v1/seg/event/310b1882-4a62-436a-99b1-ca56435b48f6:TUL/ad_break_id/ab-001/profile/</BaseURL>
      <SegmentTemplate startNumber="0" media="$RepresentationID$/$Number$.mp4?stream_id=310b1882-4a62-436a-99b1-ca56435b48f6:TUL&amp;sd=5000&amp;pd=30000" initialization="$RepresentationID$/init.mp4?stream_id=310b1882-4a62-436a-99b1-ca56435b48f6:TUL&amp;pd=30000">
        <SegmentTimeline>
          <S d="5" r="5"/>
        </SegmentTimeline>
      </SegmentTemplate>
      <AdaptationSet mimeType="video/mp4" scanType="progressive" contentType="video">
        <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
        <Representation width="1280" height="720" frameRate="25" codecs="avc1.64001f" id="Video-1200k" bandwidth="1300000">
          <InbandEventStream schemeIdUri="https://developer.apple.com/streaming/emsg-id3"/>
        </Representation>
      </AdaptationSet>
      <AdaptationSet mimeType="audio/mp4" scanType="progressive" contentType="audio">
        <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
        <Representation audioSamplingRate="48000" codecs="mp4a.40.2" id="fmp4-audio-128kbps" bandwidth="128000">
          <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
        </Representation>
      </AdaptationSet>
    </Period>
    </MPD>

To understand the response structure and status codes, refer to [Method: DASH pod manifest](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_dash_pod_manifest).

If authentication fails, you see the `x-ad-manager-dai-warning`:

    ...
    < HTTP/2 200
    < access-control-allow-headers: Authorization
    < x-ad-manager-dai-warning: Unable to create ad break due to Unauthorized error (skipping ad break creation)
    <
    <?xml version="1.0" encoding="UTF-8"?>
    <MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:_XMLSchema-instance="http://www.w3.org/2001/XMLSchema-instance" _XMLSchema-instance:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" id="201" profiles="urn:hbbtv:dash:profile:isoff-live:2012" type="static" mediaPresentationDuration="PT30S" minBufferTime="PT2S">
    <Period id="1" duration="PT30S">
    <BaseURL>https://dai.google.com/linear/pods/v1/seg/event/310b1882-4a62-436a-99b1-ca56435b48f6:TUL/ad_break_id/ab-001/profile/</BaseURL>
    <SegmentTemplate startNumber="0" media="$RepresentationID$/$Number$.mp4?stream_id=310b1882-4a62-436a-99b1-ca56435b48f6:TUL&amp;sd=5000&amp;pd=30000" initialization="$RepresentationID$/init.mp4?stream_id=310b1882-4a62-436a-99b1-ca56435b48f6:TUL&amp;pd=30000">
    <SegmentTimeline>
    <S d="5" r="5"/>
    </SegmentTimeline>
    </SegmentTemplate>
    <AdaptationSet mimeType="video/mp4" scanType="progressive" contentType="video">
    <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
    <Representation width="1280" height="720" frameRate="25" codecs="avc1.64001f" id="Video-1200k" bandwidth="1300000">
    <InbandEventStream schemeIdUri="https://developer.apple.com/streaming/emsg-id3"/>
    </Representation>
    </AdaptationSet>
    <AdaptationSet mimeType="audio/mp4" scanType="progressive" contentType="audio">
    <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
    <Representation audioSamplingRate="48000" codecs="mp4a.40.2" id="fmp4-audio-128kbps" bandwidth="128000">
    <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
    </Representation>
    </AdaptationSet>
    </Period>
    </MPD>