Skip to main content

Authorization

Last updated on
  1. Authorize access to AccelByte Cloud's API using following steps:

    1. Ensure that you have created a User and a Game Client in the Admin Portal.
    2. Open the IAM Swagger page from the OAuth2 authorize API: /iam/v3/oauth/authorize. A Request ID will be generated.
    3. Log in using the user_name and password from the Authentication API: /iam/v3/authenticate. Input the Request ID generated in the previous step. If the request succeeds, you will receive an authorization code which will be used in the next step.
    4. Generate the user token using the authorization code from the OAuth2 Access Token Generation: /iam/v3/oauth/token. If the request succeeds, you will receive a user token which will be used in Step 2.
    5. Generate an OAuth Client token using client_credentials from the OAuth2 Access Token Generation: /iam/v3/oauth/token. If the request succeeds, you will receive an OAuth Client token which will be used when implementing functions related to the DSMC.
  2. Parse the user token into the object's model with the OauthmodelTokenResposeV3 field below:

    type OauthmodelTokenResponseV3 struct {

    // access token
    // Required: true
    AccessToken *string `json:"access_token"`

    // bans
    // Required: true
    Bans []*AccountcommonJWTBanV3 `json:"bans"`

    // display name
    // Required: true
    DisplayName *string `json:"display_name"`

    // expires in
    // Required: true
    ExpiresIn *int32 `json:"expires_in"`

    // is comply
    IsComply bool `json:"is_comply,omitempty"`

    // jflgs
    Jflgs int32 `json:"jflgs,omitempty"`

    // namespace
    // Required: true
    Namespace *string `json:"namespace"`

    // namespace roles
    // Required: true
    NamespaceRoles []*AccountcommonNamespaceRole `json:"namespace_roles"`

    // permissions
    // Required: true
    Permissions []*AccountcommonPermissionV3 `json:"permissions"`

    // platform id
    PlatformID string `json:"platform_id,omitempty"`

    // platform user id
    PlatformUserID string `json:"platform_user_id,omitempty"`

    // refresh token
    // Required: true
    RefreshToken *string `json:"refresh_token"`

    // roles
    // Required: true
    Roles []string `json:"roles"`

    // token type
    // Required: true
    TokenType *string `json:"token_type"`

    // user id
    // Required: true
    UserID *string `json:"user_id"`
    }

    Our user token does not contain a User ID even though there is a User ID field in the code above. In our case, the User ID will be used in the Lobby and Session browsers. Once you have filled in the above fields, store these values in the tokenConvert variable.

    // parse token
    reqToken := req.Headers["Authorization"]
    splitToken := strings.Split(reqToken, "Bearer ")
    if len(splitToken) == 1 || len(splitToken) > 2 {
    log.Print("Token split \"Bearer\" and token authorization")
    message := fmt.Sprintf("Invalid token.")
    response := events.APIGatewayProxyResponse{StatusCode: http.StatusUnauthorized, Body: message}
    return response
    }
    reqToken = splitToken[1]
    tokenConvert, err := repository.ConvertTokenToTokenResponseV3(reqToken)
    if tokenConvert == nil {
    log.Print("Unable to convert token to response model :", err.Error())
    response := events.APIGatewayProxyResponse{StatusCode: http.StatusUnauthorized, Body: fmt.Sprintf(err.Error())}
    return response
    }
  3. Validate the user tokens and permissions using the tokenConvert function. Once completed, validate the user token with custom permissions for the role inside the validatePermissionHandler function.

    // validating permission using lambda function
    func (titleMMService *TitleMatchmakingService) validatePermissionHandler(reqToken, clientId string,
    tokenResponse *iamclientmodels.OauthmodelTokenResponseV3) (int, error) {
    var namespaceRoles []iam.NamespaceRole
    var permissions []iam.Permission

    for _, namespaceRole := range tokenResponse.NamespaceRoles {
    n := iam.NamespaceRole{
    RoleID: *namespaceRole.RoleID,
    Namespace: *namespaceRole.Namespace,
    }
    namespaceRoles = append(namespaceRoles, n)
    }
    log.Printf("namespaceRoles : %+v", namespaceRoles)

    var rangeSchedule []string
    for _, permission := range tokenResponse.Permissions {
    p := iam.Permission{
    Resource: *permission.Resource,
    Action: int(*permission.Action),
    ScheduledAction: int(permission.SchedAction),
    CronSchedule: "",
    RangeSchedule: rangeSchedule,
    }
    permissions = append(permissions, p)
    }

    // validate token
    validateAccessToken, err := titleMMService.IamClient.ValidateAccessToken(reqToken)
    if err != nil {
    log.Print("Validate access token error. Token expired.", err.Error())
    return http.StatusBadRequest, err
    }
    if !validateAccessToken {
    log.Print("Validate access token return false. ", err)
    return http.StatusUnauthorized, err
    } else {
    log.Print("Access token is a valid one.")
    }

    // validate permission
    claims := iam.JWTClaims{
    Namespace: *tokenResponse.Namespace,
    DisplayName: *tokenResponse.DisplayName,
    Roles: tokenResponse.Roles,
    AcceptedPolicyVersion: nil,
    NamespaceRoles: namespaceRoles,
    Permissions: permissions,
    Bans: nil,
    JusticeFlags: 0,
    Scope: "",
    Country: "",
    ClientID: clientId,
    IsComply: false,
    Claims: iam.JWTClaims{}.Claims,
    }
    resource := make(map[string]string, 0)
    resource["{namespace}"] = claims.Namespace
    validatePermission, err := titleMMService.IamClient.ValidatePermission(
    &claims,
    iam.Permission{
    Resource: "NAMESPACE:{namespace}:MATCHMAKING",
    Action: iam.ActionCreate,
    },
    resource,
    )

    if err != nil {
    log.Print("Unable to validate permission. Error : ", err.Error())
    return http.StatusForbidden, err
    } else {
    log.Print("Successful validate permission from iam client")
    }

    if !validatePermission {
    log.Print("Insufficient permissions")
    return http.StatusForbidden, err
    } else {
    log.Print("There's enough permission")
    }

    return http.StatusOK, nil
    }

    Permissions will be added to this role using the user token, as per the response below.

  4. Obtain the User ID from the subfield in the user token.

    claims, err := titleMMService.IamClient.ValidateAndParseClaims(reqToken)
    if claims == nil {
    log.Print("Claim is empty. Error : ", err.Error())
    message := "Claim is empty"
    response := events.APIGatewayProxyResponse{StatusCode: http.StatusUnauthorized, Body: fmt.Sprintf(message)}
    return response
    }
    if err != nil {
    log.Print("Unable to validate and parse token. Error : ", err.Error())
    response := events.APIGatewayProxyResponse{StatusCode: http.StatusUnauthorized, Body: fmt.Sprintf(err.Error())}
    return response
    }
    userId := claims.Subject
    namespace := claims.Namespace

    namespaceGame := constants.NamespaceGame

    gameMode := constants.GameMode
  5. Store the valid user token in the empty interface so you can get and use the valid token.

    // store the valid token
    errToken := tokenRepositoryImpl.Store(*tokenConvert)
    if errToken != nil {
    log.Print("Unable to store token :", errToken.Error())
    message := fmt.Sprint("Unable to store token")
    response := events.APIGatewayProxyResponse{StatusCode: http.StatusInternalServerError, Body: message}
    return response
    }
  6. Set the OAuth Client token for the DSMC service and input the registered Client ID in the GAME_CLIENT_ID field. While the Lobby and Session browsers need a user token, the DSMC needs a client token (client_credentials from a registered OAuth Client).

    // get token from game client for DSMC
    log.Print("Config Repo Game Client Id : ", configGameImpl.GetClientId())
    oauthService = iamServices.OAuth20Service{
    IamService: factory.NewIamClient(&configGameImpl),
    ConfigRepository: &configGameImpl,
    TokenRepository: &tokenRepositoryGameImpl,
    }
    err = oauthService.GrantTokenCredentials("", "")
    if err != nil {
    log.Print("Unable to grant token : ", err.Error())
    message := fmt.Sprint("Unable to grant token")
    response := events.APIGatewayProxyResponse{StatusCode: http.StatusInternalServerError, Body: message}
    return response
    }
    tokenRepo, err := oauthService.TokenRepository.GetToken()
    if err != nil {
    log.Print("Empty error : ", err.Error())
    message := fmt.Sprint("Unable to get token")
    response := events.APIGatewayProxyResponse{StatusCode: http.StatusInternalServerError, Body: message}
    return response
    }
    if tokenRepo == nil {
    log.Print("Empty tokenRepo.")
    message := fmt.Sprint("Empty token repository")
    response := events.APIGatewayProxyResponse{StatusCode: http.StatusInternalServerError, Body: message}
    return response
    }