...

Source file src/github.com/ory/fosite/handler/oauth2/introspector_jwt.go

Documentation: github.com/ory/fosite/handler/oauth2

     1  /*
     2   * Copyright © 2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   *
    16   * @author		Aeneas Rekkas <aeneas+oss@aeneas.io>
    17   * @copyright 	2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
    18   * @license 	Apache-2.0
    19   *
    20   */
    21  
    22  package oauth2
    23  
    24  import (
    25  	"context"
    26  	"time"
    27  
    28  	"github.com/ory/fosite"
    29  	"github.com/ory/fosite/token/jwt"
    30  )
    31  
    32  type StatelessJWTValidator struct {
    33  	jwt.JWTStrategy
    34  	ScopeStrategy fosite.ScopeStrategy
    35  }
    36  
    37  // AccessTokenJWTToRequest tries to reconstruct fosite.Request from a JWT.
    38  func AccessTokenJWTToRequest(token *jwt.Token) fosite.Requester {
    39  	mapClaims := token.Claims
    40  	claims := jwt.JWTClaims{}
    41  	claims.FromMapClaims(mapClaims)
    42  
    43  	requestedAt := claims.IssuedAt
    44  	requestedAtClaim, ok := mapClaims["rat"]
    45  	if ok {
    46  		switch requestedAtClaim.(type) {
    47  		case float64:
    48  			requestedAt = time.Unix(int64(requestedAtClaim.(float64)), 0).UTC()
    49  		case int64:
    50  			requestedAt = time.Unix(requestedAtClaim.(int64), 0).UTC()
    51  		}
    52  	}
    53  
    54  	clientId := ""
    55  	clientIdClaim, ok := mapClaims["client_id"]
    56  	if ok {
    57  		switch clientIdClaim.(type) {
    58  		case string:
    59  			clientId = clientIdClaim.(string)
    60  		}
    61  	}
    62  
    63  	return &fosite.Request{
    64  		RequestedAt: requestedAt,
    65  		Client: &fosite.DefaultClient{
    66  			ID: clientId,
    67  		},
    68  		// We do not really know which scopes were requested, so we set them to granted.
    69  		RequestedScope: claims.Scope,
    70  		GrantedScope:   claims.Scope,
    71  		Session: &JWTSession{
    72  			JWTClaims: &claims,
    73  			JWTHeader: &jwt.Headers{
    74  				Extra: token.Header,
    75  			},
    76  			ExpiresAt: map[fosite.TokenType]time.Time{
    77  				fosite.AccessToken: claims.ExpiresAt,
    78  			},
    79  			Subject: claims.Subject,
    80  		},
    81  		// We do not really know which audiences were requested, so we set them to granted.
    82  		RequestedAudience: claims.Audience,
    83  		GrantedAudience:   claims.Audience,
    84  	}
    85  }
    86  
    87  func (v *StatelessJWTValidator) IntrospectToken(ctx context.Context, token string, tokenUse fosite.TokenUse, accessRequest fosite.AccessRequester, scopes []string) (fosite.TokenUse, error) {
    88  	t, err := validate(ctx, v.JWTStrategy, token)
    89  	if err != nil {
    90  		return "", err
    91  	}
    92  
    93  	// TODO: From here we assume it is an access token, but how do we know it is really and that is not an ID token?
    94  
    95  	requester := AccessTokenJWTToRequest(t)
    96  
    97  	if err := matchScopes(v.ScopeStrategy, requester.GetGrantedScopes(), scopes); err != nil {
    98  		return fosite.AccessToken, err
    99  	}
   100  
   101  	accessRequest.Merge(requester)
   102  
   103  	return fosite.AccessToken, nil
   104  }
   105  

View as plain text